我已经用Netbeans编写了大约一年的Java代码,并编写了大量的数据操作代码,用于在屏幕上绘制图形。我通常在主窗口中植入一个JPanel对象,编写自定义绘图代码,并根据需要调用repaint()方法。
但是今天,我第一次试图从一个类(对象)调用一个面板上的重绘,而不是包含该面板的类。虽然编译器发现没有任何问题,并且在调试模式下,它单步执行到外部调用重绘,实际上没有重绘,并且代码实际上没有进入重绘方法。
我写了一个简约程序来演示这个问题,如下所示(Main省略,因为它只包含设置两个屏幕面板的代码。)
---类的描述,首先包含绘图表面,其他重绘调用---
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Panel1 extends JComponent
{
GraphPnl graphPnl;
boolean colorFlag;
public Panel1()
{
setLayout(null);
colorFlag = true;
graphPnl = new GraphPnl();
graphPnl.setBounds(10, 10, 110, 110);
graphPnl.setBackground(Color.black);
add(graphPnl);
}//Panel1()
public class GraphPnl extends JPanel
{
//just draws a line segment, toggling color
@Override
public void paint(Graphics g)
{
super.paint(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
if (colorFlag) {g2.setColor(Color.red);} else {g2.setColor(Color.green);}
g2.drawLine(10, 10, 50, 50);
}//paint
}//GraphPnl
}//Panel1
import javax.swing.*;
import java.awt.event.*;
public class Panel2 extends JComponent
{
JButton testBtn;
TestAction testAction;
Panel1 p1;
public Panel2()
{
p1 = new Panel1();
testBtn = new JButton("Click");
testBtn.setBounds(10, 10, 80, 30);
add(testBtn);
testAction = new TestAction();
testBtn.addActionListener(testAction);
}//Panel2()
public class TestAction implements ActionListener
{
public void actionPerformed(ActionEvent evt)
{
p1.colorFlag = ! p1.colorFlag;
p1.graphPnl.repaint();
}
}//TestAction
}//Panel2
如果有人对此有任何见解,或者知道某种解决方法,我会很高兴听到 来自你
提前感谢任何见解。
John Doner
答案 0 :(得分:1)
“Swing程序应该覆盖paintComponent()
,而不是覆盖paint()
。” - Painting in AWT and Swing: The Paint Methods。
省略了
main
,因为它只包含设置两个屏幕面板的代码。
验证您是否在EDT上构建GUI,如文章Initial Threads所示。
附录:这是一个显示两个原则的例子:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
/** @see http://stackoverflow.com/questions/4282159 */
public class GraphPanel extends JPanel {
private boolean colorFlag;
public GraphPanel() {
this.setPreferredSize(new Dimension(640, 480));
}
public void toggle() {
colorFlag = !colorFlag;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
if (colorFlag) {
g2.setColor(Color.red);
} else {
g2.setColor(Color.blue);
}
g2.drawLine(0, 0, getWidth(), getHeight());
}
private void display() {
JFrame f = new JFrame("GraphPanel");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(this, BorderLayout.CENTER);
f.add(new ControlPanel(this), BorderLayout.SOUTH);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
new GraphPanel().display();
}
});
}
}
class ControlPanel extends JPanel {
public ControlPanel(final GraphPanel gp) {
this.add(new JButton(new AbstractAction("Click") {
@Override
public void actionPerformed(ActionEvent e) {
gp.toggle();
gp.repaint();
}
}));
}
}
附录:如@ camickr的评论中所述,A Visual Guide to Layout Managers可能有助于指导您的布局选择。
答案 1 :(得分:1)
Main is ommitted,因为它只包含设置两个屏幕面板的代码。)
嗯,根据定义,当您遇到问题时,在问题解决之前您不知道代码是什么或不相关。因此,应发布完整的SSCCE。
作为一个疯狂的猜测,我会说你的组件的大小为0,所以没有什么可画的。
我通常在主窗口中植入一个JPanel对象,编写自定义绘图代码,并根据需要调用repaint()方法
您可能很幸运,因为您将面板添加到BorderLayout的中心,该面板自动为面板提供框架可用的所有空间。
trashgod的示例显示了一种设置自定义组件的首选大小的方法。另一种方法是覆盖getPreferredSize()方法以返回正确的值。
你真的应该学习如何使用布局管理器而不是使用空布局,你将来会避免这样的问题。除非您有拖放类型的应用程序,否则无需使用空布局。
答案 2 :(得分:0)
我相信在绘制JComponent时,剪辑区域设置为该JComponent。因此,如果其他组件尝试绘制(或者如果你调用它们重绘),它们就不会,因为剪切。