这里是应该绘制JComponents的表单中的相关代码 - 这段代码创建并添加到表单中的JComponent并将其添加到ArrayList,因为我需要以后能够销毁组件。
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Random;
import javax.swing.JOptionPane;
public class frmMain extends javax.swing.JFrame implements ActionListener {
ArrayList<Pocitadlo> poc;
Random rnd;
/**
* Creates new form frmMain
*/
public frmMain() {
initComponents();
poc = new ArrayList<Pocitadlo>();
rnd = new Random();
// Pocitadlo tmp = new Pocitadlo(100, 40, 40, getFont());
// tmp.addActionListener(this);
// this.add(tmp);
// tmp.start();
}
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
int val, x, y;
val = 20;
x = (this.getWidth() / 2) - 10 + rnd.nextInt(20);
y = (this.getHeight() / 2) - 10 + rnd.nextInt(20);
try{
val = Integer.parseInt(txtCounterValue.getText());
Pocitadlo tmp = new Pocitadlo(val, x, y, getFont());
tmp.addActionListener(this);
poc.add(tmp);
tmp.setVisible(true);
tmp.start();
this.add(tmp);
this.setTitle("Počet počítadiel: " + this.getComponentCount());
repaint();
tmp.repaint();
} catch(Exception e){
JOptionPane.showMessageDialog(this, "Nesprávne zadaná alebo prázdna hodnota počítadla. Hodnota musí byť celé číslo.", "Chyba", JOptionPane.ERROR_MESSAGE);
}
}
@Override
public void actionPerformed(ActionEvent e){
if(e.getActionCommand().equals("counterFinished")){
Pocitadlo tmp = (Pocitadlo)e.getSource();
poc.remove(tmp);
this.setTitle("Počet počítadiel: " + poc.size());
this.remove(tmp);
}
}
这里是JComponents的代码我正在添加并且预期会被绘制:
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JComponent;
import javax.swing.Timer;
public class Pocitadlo extends JComponent implements MouseListener, ActionListener {
private int maxValue, value;
private Boolean isRunning, isDisplayed;
private Timer valueTimer, blinkTimer;
private ActionListener actionListener;
private Font font;
public Pocitadlo(int timeout, int x, int y, Font f){
isRunning = false;
isDisplayed = true;
maxValue = value = timeout;
valueTimer = new Timer(1000, this);
valueTimer.setActionCommand("valueTimer");
blinkTimer = new Timer(200, this);
blinkTimer.setActionCommand("blinkTimer");
this.setBounds(x, y, 100, 50);
}
public void start(){
isRunning = true;
valueTimer.start();
}
public void stop(){
isRunning = false;
valueTimer.stop();
}
@Override
public void actionPerformed(ActionEvent e){
if(e.getActionCommand().equals("valueTimer")){
value--;
if(actionListener != null){
repaint();
actionListener.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "counterTick"));
}
if(value == 0 && actionListener != null){
isRunning = false;
valueTimer.stop();
actionListener.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "counterFinished"));
}
if(value < maxValue / 2 && !blinkTimer.isRunning()) blinkTimer.start();
}
if(e.getActionCommand().equals("blinkTimer")){
isDisplayed = !isDisplayed;
repaint();
}
}
public void addActionListener(ActionListener listener){
actionListener = listener;
}
@Override
public void mouseClicked(MouseEvent e) {
value += 5000;
if(value > maxValue) value = maxValue;
repaint();
}
@Override
public void paintComponent(Graphics g){
g.setColor(Color.red);
g.fillRect(getX(), getY(), getWidth(), getHeight());
if(isDisplayed){
g.setColor(Color.green);
g.fillRect(getX(), getY(), getWidth(), getHeight());
g.setColor(Color.black);
//g.setFont(font);
g.drawString(value + "/" + maxValue, 0, 0);
}
//super.paintComponent(g);
}
}
这没有任何结果 - JComponents被创建并正确地添加到ArrayList,并且它的paintComponent方法运行,以及计时器事件,组件也在倒计时时至少从ArrayList中被正确删除达到0,但没有画任何东西,我不明白为什么。
请注意frmMain构造函数中的注释代码有效,如果取消注释,它会绘制JComponent ......好吧...只是矩形,不会绘制任何文本,但我想这是另一个问题,但是,如果你也愿意帮助那个问题,那我很高兴。
另外,如果我错误地使用了动作事件和听众,请忽略它,我是Java的初学者,并且想知道如何正确地做到这一点,但是后来< / b>,现在我只需要让这段代码工作,所以请关注这个问题,谢谢。
是的,有一些死机,比如传递给组件的字体,这些都是我试图让drawString工作的原因。
答案 0 :(得分:3)
你的项目遭受了许多关于如何在Swing中进行绘画的误解。
因为(在我测试的时候)你没有提供完整的代码,我不得不做出一些假设。
您的期望是JFrame
的内容窗格使用null
布局。我发现很难看到你如何管理它并在框架上有其他组件。在任何情况下,我都会隔离一个单独的容器,作为Pocitadlo
的“主要”视图。这允许您继续使用布局管理器来管理其他组件。
我有点担心您将整个Pocitadlo
生成代码捕获到try-catch
只是为了捕获数字转换。由于您已经应用了默认值,因此将转换捕获到其自己的try-catch
中是合理的,如果失败则忽略它(根据需要显示消息)。现在我从外面进来,所以你可能会看到需要这个,它只是引起了我的注意......
您的valueTimer
actionPerformed
代码略显错误,因为blinkTimer
即使在valueTimer
完成后也可以继续运行。我通过将两个if
语句合并到一个if-else
语句而不是......
if (value == 0 && actionListener != null) {
isRunning = false;
valueTimer.stop();
actionListener.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "counterFinished"));
blinkTimer.stop();
} else if (value < maxValue / 2 && !blinkTimer.isRunning()) {
blinkTimer.start();
}
我个人会在JPanel
上使用JComponent
。 JPanel
开头是不透明的。
主要问题在于paintComponent
方法。
super.paintComponent
,而对于不透明的组件,应首先调用它。g.fillRect(getX(), getY(), getWidth(), getHeight());
。这实际上是错误的。图形上下文已经被翻译,因此组件/图形的x / y位置现在等于0x0。请仔细阅读Painting in AWT and Swing以获得更好的解释,但基本上,这意味着,您绘制区域的左上角现在是0x0。Font
s上升值调整y位置来补偿此情况。
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class TestRepaint01 {
public static void main(String[] args) {
new TestRepaint01();
}
public TestRepaint01() {
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) {
}
MainFrame frame = new MainFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(200, 200);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class MainFrame extends javax.swing.JFrame implements ActionListener {
ArrayList<Pocitadlo> poc;
Random rnd;
private JPanel body;
/**
* Creates new form frmMain
*/
public MainFrame() {
setLayout(new BorderLayout());
poc = new ArrayList<Pocitadlo>();
rnd = new Random();
body = new JPanel(null);
add(body);
JButton btn = new JButton("Add");
btn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
int val, x, y;
val = 20;
x = (getWidth() / 2) - 10 + rnd.nextInt(20);
y = (getHeight() / 2) - 10 + rnd.nextInt(20);
// try {
// val = Integer.parseInt(txtCounterValue.getText());
Pocitadlo tmp = new Pocitadlo(val, x, y, getFont());
tmp.addActionListener(MainFrame.this);
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.weightx = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
poc.add(tmp);
tmp.start();
body.add(tmp);
body.repaint();
setTitle("Počet počítadiel: " + getComponentCount());
// } catch (Exception e) {
// JOptionPane.showMessageDialog(this, "Nesprávne zadaná alebo prázdna hodnota počítadla. Hodnota musí byť celé číslo.", "Chyba", JOptionPane.ERROR_MESSAGE);
// }
}
});
add(btn, BorderLayout.SOUTH);
}
@Override
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals("counterFinished")) {
System.out.println("Counter finished");
Pocitadlo tmp = (Pocitadlo) e.getSource();
poc.remove(tmp);
this.setTitle("Počet počítadiel: " + poc.size());
body.remove(tmp);
// body.revalidate();
body.repaint();
}
}
}
public class Pocitadlo extends JPanel implements MouseListener, ActionListener {
private int maxValue, value;
private Boolean isRunning, isDisplayed;
private Timer valueTimer, blinkTimer;
private ActionListener actionListener;
private Font font;
public Pocitadlo(int timeout, int x, int y, Font f) {
isRunning = false;
isDisplayed = true;
maxValue = value = timeout;
valueTimer = new Timer(1000, this);
valueTimer.setActionCommand("valueTimer");
blinkTimer = new Timer(200, this);
blinkTimer.setActionCommand("blinkTimer");
this.setBounds(x, y, 100, 50);
}
@Override
public void removeNotify() {
super.removeNotify();
stop();
blinkTimer.stop();
}
public void start() {
isRunning = true;
valueTimer.start();
}
public void stop() {
isRunning = false;
valueTimer.stop();
}
@Override
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals("valueTimer")) {
value--;
System.out.println("value = " + value);
if (actionListener != null) {
repaint();
actionListener.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "counterTick"));
}
if (value == 0 && actionListener != null) {
isRunning = false;
valueTimer.stop();
actionListener.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "counterFinished"));
blinkTimer.stop();
} else if (value < maxValue / 2 && !blinkTimer.isRunning()) {
blinkTimer.start();
}
}
if (e.getActionCommand().equals("blinkTimer")) {
System.out.println("Blink");
isDisplayed = !isDisplayed;
repaint();
}
}
public void addActionListener(ActionListener listener) {
actionListener = listener;
}
@Override
public void mouseClicked(MouseEvent e) {
value += 5000;
if (value > maxValue) {
value = maxValue;
}
repaint();
}
@Override
public void mouseExited(MouseEvent e) {
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.red);
// location bad
g.fillRect(0, 0, getWidth(), getHeight());
if (isDisplayed) {
g.setColor(Color.green);
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(Color.black);
//g.setFont(font);
FontMetrics fm = g.getFontMetrics();
g.drawString(value + "/" + maxValue, 0, fm.getAscent());
}
g.drawRect(0, 0, getWidth() - 1, getHeight() - 1);
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
}
}
您遇到的任何问题都不是超级关键(当然,您的程序不能达到您想要的效果),并建议您在代码能力方面达到顶峰。我这样说,因为我犯了同样的错误......;)
仔细查看2D Graphics和Custom Painting
我还会看一下Code Conventions for the Java Programming Language因为如果你不跟随他们就会惹恼别人;)