我有一个程序,可以使用绘制方法将车辆对象(例如汽车形状)绘制到 JFrame 上。然而,每当我单击屏幕来绘制车辆时,我都必须刷新窗 Eloquent 能显示它们即使添加了 repaint() 方法。
<小时/>第一张图片显示了我点击的位置。什么都没发生。
最小化并打开窗口后。
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.Iterator;
import java.util.LinkedList;
import javax.swing.JFrame;
/** Program specs: Draws shapes (Vehicles) that are contained within LinkedLists.
* When a shape is drawn over another shape it 'joins' its list. (not implemented yet, not my issue)
*/
/**
Creates JFrame
*/
public class FramePanel extends JFrame implements MouseListener
{
private static final int FRAME_WIDTH = 600;
private static final int FRAME_HEIGHT = 600;
Car car; // Car is a subclass of Vehicle. It only contains a draw method.
//Vehicle is an abstract class that only contains a draw method
LinkedList<LinkedList<Vehicle>> list = new LinkedList<LinkedList<Vehicle>>();
LinkedList<Vehicle> temp = new LinkedList <Vehicle>();
/**
Constructs the frame.
*/
public FramePanel()
{
addMouseListener(this);
setSize(FRAME_WIDTH, FRAME_HEIGHT);
repaint();
}
@Override
public void mouseClicked(MouseEvent evt) {
car = new Car (evt.getX(), evt.getY());
temp.add(car); //Add Vehicle to LinkedList
list.add(temp); //Add LinkedList to Collection of LinkedLists
}
public void mouseEntered(MouseEvent arg0) {}
public void mouseExited(MouseEvent arg0) {}
public void mousePressed(MouseEvent arg0) {}
public void mouseReleased(MouseEvent arg0) {}
public void paint(Graphics g) {
super.paintComponents(g) ;
Graphics2D g2 = (Graphics2D) g;
for (LinkedList<Vehicle> veh : list){ // list is collection of Linked Lists
Iterator<Vehicle> it = veh.iterator();
while (it.hasNext()){
it.next().draw(g2);
}
}
}
public static void main(String[] args)
{
JFrame frame = new FramePanel();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("Viewer");
frame.setVisible(true);
}
}
<小时/>
注意:如果我在 Paint(Graphic g) 方法中添加 repaint() 语句,汽车将被绘制,但在构造函数中使用/不使用 repaint() 时会出现不良闪烁。我不想要这个。
最佳答案
在 mouseClicked
方法的最后一行添加对 repaint()
的调用即可解决此问题。
但是,还有其他几点:
- 不要扩展
JFrame
(尤其是不要重写JFrame
的paint
方法)。相反,使用JPanel
进行绘制,并重写其paintComponent
方法。 - 不要让顶级类实现
MouseListener
接口(interface) - 请勿将列表声明为
LinkedList
,而仅声明为List
( What does it mean to "program to an interface"? ) - GUI 应在 Event-Dispatch-Thread 上创建
- 字段应为私有(private)(如果可能的话,应为最终)
一些清理工作:
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.LinkedList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class FramePanel extends JPanel
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
createAndShowGUI();
}
});
}
private static void createAndShowGUI()
{
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
FramePanel framePanel = new FramePanel();
f.getContentPane().add(framePanel);
f.setSize(600,600);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
private final List<List<Vehicle>> list = new LinkedList<List<Vehicle>>();
/**
Constructs the panel.
*/
public FramePanel()
{
addMouseListener(new MouseAdapter()
{
@Override
public void mouseClicked(MouseEvent e)
{
addCarAt(e.getX(), e.getY());
}
});
}
private void addCarAt(int x, int y)
{
Car car = new Car(x, y);
List<Vehicle> temp = new LinkedList<Vehicle>();
temp.add(car); //Add Vehicle to LinkedList
list.add(temp); //Add LinkedList to Collection of LinkedLists
repaint();
}
@Override
protected void paintComponent(Graphics gr)
{
super.paintComponent(gr) ;
Graphics2D g = (Graphics2D)gr;
for (List<Vehicle> veh : list) // list is collection of Linked Lists
{
for (Vehicle v : veh)
{
v.draw(g);
}
}
}
}
关于最小化/重新打开窗口后 Java JFrame 重新绘制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22736029/