MigLayout 和 JLabel 衍生物表现出奇怪的行为并且不遵循布局
MigLayout and JLabel derivative show strange behaviour and don't follow layout
我正在使用 Java Swing 和 MigLayout(多棒的工具!)在 java 中创建项目,但我遇到了问题。
为了尽可能大地显示每个字符串,我创建了 JLabel 的子 class,它根据组件的大小更改字体,我将在示例 I 中附上代码会提供。
项目很大,嵌套了很多panel,我还临时改了mainwindow的内容,之后验证一切。
但是,如果我尝试在 MigLayout 中使用组件的单元格配置,一切都是错误的。
如果我使用相同的布局,具有相同的约束,但不是使用我的自定义标签,而是使用普通的 JLabel,一切都很好。
这里是示例的要点:
https://gist.github.com/bracco23/c47975ede0d857ac3b134f197c4371a2
代码在两个文件中:
JAdaptiveLabel.java,自定义组件,只要文本更改或按需重新计算最佳字体大小。
test.java,模拟示例。更改 CUSTOM,您可以在我的组件和普通 JLabel 之间切换并查看差异。预期的布局是带有普通 JLabel 的布局。
任何人都可以告诉我哪里出了问题,我该如何解决?
好的,经过努力我解决了
测试后,我得出的结论(很明显)是我的 JAdaptiveLabel 出了点问题。所以我在网上搜索了另一个版本,看看是我的实现还是自适应性本身的问题。
我得出这个答案:@Warren K
我按原样使用了他的 class 并且它起作用了,所以我的实现被窃听了。
我从他的版本开始改变了调整大小的算法,因为他的是迭代的(改变大小直到你找到完美的)而我的是数学的(只得到相关的度量并计算出完美的大小)。
成功了。现在布局得到正确处理,如果我调整 window.
的大小,标签会更改字体大小
此处修改代码:
package it.bracco23.util;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
// Improved version of http://java-sl.com/tip_adapt_label_font_size.html
public class JAdaptiveLabel extends JLabel {
private Graphics g;
private boolean init = false;
public JAdaptiveLabel(String text, Icon icon, int horizontalAlignment) {
super(text, icon, horizontalAlignment);
init();
}
public JAdaptiveLabel(String text, int horizontalAlignment) {
super(text, horizontalAlignment);
init();
}
public JAdaptiveLabel(String text) {
super(text);
init();
}
public JAdaptiveLabel(Icon image, int horizontalAlignment) {
super(image, horizontalAlignment);
init();
}
public JAdaptiveLabel(Icon image) {
super(image);
init();
}
public JAdaptiveLabel() {
init();
}
protected void init() {
addComponentListener(new ComponentAdapter() {
public void componentResized(ComponentEvent e) {
adaptLabelFont(JAdaptiveLabel.this);
}
});
init = true;
}
protected void adaptLabelFont(JLabel l) {
if (g==null) {
return;
}
Rectangle r = l.getBounds();
Insets ins = l.getInsets();
r.x = 0;
r.y = 0;
Font f = l.getFont();
Dimension dim = getTextSize(l, f);
//0.9f is a scale factor to don't let the text take too much space
//without it will work, but the text may appear to close to the border
float xFactor = ((r.width - ins.left - ins.right) * 0.9f) / dim.width;
float yFactor = ((r.height - ins.top - ins.bottom) * 0.9f) / dim.height;
/*the next lines assure the scaling factors are not zero (can happen)
and are different enough from 1. Without this last check, it might happen
that the font starts to cycle between two sizes. */
xFactor = (xFactor != 0 && Math.abs(xFactor - 1)>0.1) ? xFactor : 1;
yFactor = (yFactor != 0 && Math.abs(xFactor - 1)>0.1) ? yFactor : 1;
float fontSize = f.getSize() * Math.min(xFactor, yFactor);
setFont(f.deriveFont(f.getStyle(), fontSize));
repaint();
}
private Dimension getTextSize(JLabel l, Font f) {
Dimension size = new Dimension();
FontMetrics fm = g.getFontMetrics(f);
size.width = fm.stringWidth(l.getText());
size.height = fm.getHeight();
return size;
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
this.g=g;
}
@Override
public void setText(String text) {
super.setText(text);
if(init){
adaptLabelFont(this);
}
}
}
如果你在我给出的例子中使用这个版本的class,一切正常!
P.S。我还在 setText 中添加了对调整大小方法的调用,因为当标签调整大小时或更改其内容时必须更改大小。
我正在使用 Java Swing 和 MigLayout(多棒的工具!)在 java 中创建项目,但我遇到了问题。
为了尽可能大地显示每个字符串,我创建了 JLabel 的子 class,它根据组件的大小更改字体,我将在示例 I 中附上代码会提供。
项目很大,嵌套了很多panel,我还临时改了mainwindow的内容,之后验证一切。
但是,如果我尝试在 MigLayout 中使用组件的单元格配置,一切都是错误的。
如果我使用相同的布局,具有相同的约束,但不是使用我的自定义标签,而是使用普通的 JLabel,一切都很好。
这里是示例的要点:
https://gist.github.com/bracco23/c47975ede0d857ac3b134f197c4371a2
代码在两个文件中:
JAdaptiveLabel.java,自定义组件,只要文本更改或按需重新计算最佳字体大小。
test.java,模拟示例。更改 CUSTOM,您可以在我的组件和普通 JLabel 之间切换并查看差异。预期的布局是带有普通 JLabel 的布局。
任何人都可以告诉我哪里出了问题,我该如何解决?
好的,经过努力我解决了
测试后,我得出的结论(很明显)是我的 JAdaptiveLabel 出了点问题。所以我在网上搜索了另一个版本,看看是我的实现还是自适应性本身的问题。
我得出这个答案:@Warren K
我按原样使用了他的 class 并且它起作用了,所以我的实现被窃听了。
我从他的版本开始改变了调整大小的算法,因为他的是迭代的(改变大小直到你找到完美的)而我的是数学的(只得到相关的度量并计算出完美的大小)。
成功了。现在布局得到正确处理,如果我调整 window.
的大小,标签会更改字体大小此处修改代码:
package it.bracco23.util;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
// Improved version of http://java-sl.com/tip_adapt_label_font_size.html
public class JAdaptiveLabel extends JLabel {
private Graphics g;
private boolean init = false;
public JAdaptiveLabel(String text, Icon icon, int horizontalAlignment) {
super(text, icon, horizontalAlignment);
init();
}
public JAdaptiveLabel(String text, int horizontalAlignment) {
super(text, horizontalAlignment);
init();
}
public JAdaptiveLabel(String text) {
super(text);
init();
}
public JAdaptiveLabel(Icon image, int horizontalAlignment) {
super(image, horizontalAlignment);
init();
}
public JAdaptiveLabel(Icon image) {
super(image);
init();
}
public JAdaptiveLabel() {
init();
}
protected void init() {
addComponentListener(new ComponentAdapter() {
public void componentResized(ComponentEvent e) {
adaptLabelFont(JAdaptiveLabel.this);
}
});
init = true;
}
protected void adaptLabelFont(JLabel l) {
if (g==null) {
return;
}
Rectangle r = l.getBounds();
Insets ins = l.getInsets();
r.x = 0;
r.y = 0;
Font f = l.getFont();
Dimension dim = getTextSize(l, f);
//0.9f is a scale factor to don't let the text take too much space
//without it will work, but the text may appear to close to the border
float xFactor = ((r.width - ins.left - ins.right) * 0.9f) / dim.width;
float yFactor = ((r.height - ins.top - ins.bottom) * 0.9f) / dim.height;
/*the next lines assure the scaling factors are not zero (can happen)
and are different enough from 1. Without this last check, it might happen
that the font starts to cycle between two sizes. */
xFactor = (xFactor != 0 && Math.abs(xFactor - 1)>0.1) ? xFactor : 1;
yFactor = (yFactor != 0 && Math.abs(xFactor - 1)>0.1) ? yFactor : 1;
float fontSize = f.getSize() * Math.min(xFactor, yFactor);
setFont(f.deriveFont(f.getStyle(), fontSize));
repaint();
}
private Dimension getTextSize(JLabel l, Font f) {
Dimension size = new Dimension();
FontMetrics fm = g.getFontMetrics(f);
size.width = fm.stringWidth(l.getText());
size.height = fm.getHeight();
return size;
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
this.g=g;
}
@Override
public void setText(String text) {
super.setText(text);
if(init){
adaptLabelFont(this);
}
}
}
如果你在我给出的例子中使用这个版本的class,一切正常!
P.S。我还在 setText 中添加了对调整大小方法的调用,因为当标签调整大小时或更改其内容时必须更改大小。