Java JFrame组件能够通过重绘调用paintComponent,尽管使用flowlayout
我在FlowLayout中有一个JFrame,其中添加了多个JLabel,但是当我在JLabel上调用repaint时,它们的paintComponent没有被调用。如果删除FlowLayout,则仅显示最后添加的JLabel并正确重新绘制。我试着用一个面板,但没用。但我不确定我是否正确使用了它Java JFrame组件能够通过重绘调用paintComponent,尽管使用flowlayout,java,swing,concurrency,jframe,paintcomponent,Java,Swing,Concurrency,Jframe,Paintcomponent,我在FlowLayout中有一个JFrame,其中添加了多个JLabel,但是当我在JLabel上调用repaint时,它们的paintComponent没有被调用。如果删除FlowLayout,则仅显示最后添加的JLabel并正确重新绘制。我试着用一个面板,但没用。但我不确定我是否正确使用了它 import java.awt.Dimension; import java.awt.EventQueue; import java.awt.FlowLayout; import java.awt.To
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.Toolkit;
import javax.swing.JFrame;
public class RacingLetters {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
final JFrame jframe = new JFrame();
jframe.setTitle("Racing letters");
jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//jframe.setExtendedState(Frame.MAXIMIZED_BOTH);
Dimension dimension = Toolkit.getDefaultToolkit().getScreenSize();
int x = (int) ((dimension.getWidth() - jframe.getWidth()) / 2);
int y = (int) ((dimension.getHeight() - jframe.getHeight()) / 2);
jframe.setLocation(x, y);
jframe.setMinimumSize(new Dimension(500, 200));
FlowLayout fl = new FlowLayout();
jframe.setLayout(fl);
//jframe.setLayout(null);
jframe.setVisible(true);
StringBuffer[] stringBufferArray = new StringBuffer[20];
char ch = 'A';
int yy = 20;
for (int i = 0; i < 5; i++) {
stringBufferArray[i] = new StringBuffer("");
BufferThread bt = new BufferThread(stringBufferArray[i], ch, 10, yy);
//pane.add(bt);
jframe.add(bt);
new Thread(bt).start();
ch++;
yy += 20;
}
}
});
}
}
导入java.awt.Dimension;
导入java.awt.EventQueue;
导入java.awt.FlowLayout;
导入java.awt.Toolkit;
导入javax.swing.JFrame;
公开类种族歧视信{
公共静态void main(字符串[]args){
invokeLater(新的Runnable(){
公开募捐{
最终JFrame JFrame=新JFrame();
jframe.setTitle(“赛车字母”);
jframe.setDefaultCloseOperation(jframe.EXIT_ON_CLOSE);
//setExtendedState(Frame.MAXIMIZED_二者);
维度=Toolkit.getDefaultToolkit().getScreenSize();
intx=(int)((dimension.getWidth()-jframe.getWidth())/2);
int y=(int)((dimension.getHeight()-jframe.getHeight())/2);
jframe.setLocation(x,y);
jframe.setMinimumSize(新尺寸(500200));
FlowLayout fl=新的FlowLayout();
jframe.setLayout(fl);
//jframe.setLayout(空);
jframe.setVisible(true);
StringBuffer[]stringBufferArray=新的StringBuffer[20];
char ch='A';
int-yy=20;
对于(int i=0;i<5;i++){
stringBufferArray[i]=新的StringBuffer(“”);
BufferThread bt=新的BufferThread(stringBufferArray[i],ch,10,yy);
//窗格。添加(bt);
jframe.add(bt);
新线程(bt.start();
ch++;
yy+=20;
}
}
});
}
}
导入java.awt.Font;
导入java.awt.Graphics;
导入java.awt.Graphics2D;
导入java.util.Random;
导入java.util.logging.Level;
导入java.util.logging.Logger;
导入javax.swing.JLabel;
公共类BufferThread扩展JLabel实现可运行{
char ch;
对某人施加压力;
int x,y;
BufferThread(StringBuffer sb、char ch、int x、int y){
这是;
this.ch=ch;
这个.x=x;
这个。y=y;
}
@凌驾
公开募捐{
Random rand=新的Random();
对于(int i=0;i<5;i++){
某人附加(ch);
System.out.println(x+“”+y+“”+ch);
重新油漆();
试一试{
线程睡眠(兰特nextInt(500));
}捕获(中断异常例外){
Logger.getLogger(BufferThread.class.getName()).log(Level.SEVERE,null,ex);
}
}
}
公共组件(图形g){
//System.out.println(x+“”+y+“”+ch);
//系统输出打印项次(“aaaa”);
//干掉印刷品(sb);
图形2d g2=(图形2d)g;
Font f=新字体(“衬线”,Font.PLAIN,24);
//if(sb.toString().indexOf(“E”)<0)
g2.抽绳(sb.toString(),x,y);
}
}
核心问题是JLabel
没有向框架的布局管理器提供任何关于它希望有多大的信息。它实际上也没有告诉框架的布局管理器它已经更新并且需要调整大小
我无法理解你们为什么要在标签上画文字,因为标签的设计就是这样的
在处理Swing组件时,应避免使用Thread
,并应尽可能使用javax.Swing.Timer
和SwingWorker
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Ticker {
public static void main(String[] args) {
new Ticker();
}
public Ticker() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException ex) {
} catch (InstantiationException ex) {
} catch (IllegalAccessException ex) {
} catch (UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new FlowLayout());
frame.add(new TickerLabel());
frame.setSize(100, 100);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TickerLabel extends JLabel {
private int counter;
public TickerLabel() {
Timer timer = new Timer(500, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (counter > 4) {
((Timer)e.getSource()).stop();
} else {
String text = getText();
text += (char)(((int)'A') + counter);
setText(text);
}
counter++;
}
});
timer.setRepeats(true);
timer.setCoalesce(true);
timer.start();
}
}
}
Swing组件不应该在事件分派线程之外使用,因此您应该以不同的方式进行此操作。我建议使用Swing计时器。顺便说一下,组件的大小似乎保持不变,为0x0。由于这个原因,
repaint
发现没有必要调用paintComponent
。不要重写JLabel来实现线程或进行自定义绘制。@Lonenebula我想你在这里一针见血了……你知道为什么吗?做得很好!我没有仔细检查他的代码,没有意识到为什么大小不会改变。不过,他希望延迟是随机的,这样多家唱片公司就可以竞争。@Lonenebula我相信OP可以想出如何实现这一点;)
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Ticker {
public static void main(String[] args) {
new Ticker();
}
public Ticker() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException ex) {
} catch (InstantiationException ex) {
} catch (IllegalAccessException ex) {
} catch (UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new FlowLayout());
frame.add(new TickerLabel());
frame.setSize(100, 100);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TickerLabel extends JLabel {
private int counter;
public TickerLabel() {
Timer timer = new Timer(500, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (counter > 4) {
((Timer)e.getSource()).stop();
} else {
String text = getText();
text += (char)(((int)'A') + counter);
setText(text);
}
counter++;
}
});
timer.setRepeats(true);
timer.setCoalesce(true);
timer.start();
}
}
}