gpt4 book ai didi

java - 自定义 JComponent 拒绝绘制(如果添加到 ArrayList)

转载 作者:行者123 更新时间:2023-12-01 23:55:38 25 4
gpt4 key购买 nike

这里是应该绘制 JComponent 的表单中的相关代码 - 该代码创建 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);
}
}

这是我正在添加并天真地期望绘制的 JComponent 的代码:

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);
}
}
  1. 这不会产生任何结果 - JComponent 已创建并至少正确添加到 ArrayList,并且其 PaintComponent 方法运行,以及计时器事件,倒计时时组件也至少从 ArrayList 正确删除达到 0,但没有绘制任何东西,我不知道为什么。

  2. 请注意,frmMain 构造函数中的注释代码是有效的,如果未注释,它会绘制 JComponent...好吧...只是矩形,不会绘制任何文本,但我认为这是另一个不过,如果您也愿意帮助解决这个问题,我会很高兴。

  3. 另外,如果我错误地使用了 Action 事件和监听器,请忽略这一点,我是 Java 初学者,想知道如何正确执行,但稍后 ,现在我只需要让这段代码正常工作,所以请关注这个问题,谢谢。

  4. 是的,有一些死的东西,比如传递给组件的字体,这些是我尝试让drawString工作的剩余部分。

最佳答案

您的项目对 Swing 中的绘画工作原理存在一些非常基本的误解。

因为(在我测试它时)您没有提供完整的代码,所以我不得不做出一些假设。

您的期望是 JFrame 的内容 Pane 正在使用 null布局。我发现很难看出你将如何管理它并在框架上放置其他组件。无论如何,我会隔离一个单独的容器来充当您的 Pocitadlo 的“主” View 。 。这允许您继续使用布局管理器来管理其他组件。

我有点担心你会捕获整个 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超过JComponentJPanel一开始就是不透明的。

主要问题在你身上paintComponent方法。

  1. 您应该始终调用 super.paintComponent ,并且在不透明组件上应该首先调用它。
  2. 您似乎认为在绘画时必须纠正组件位置,例如 g.fillRect(getX(), getY(), getWidth(), getHeight()); 。这其实是错误的。图形上下文已被平移,因此组件/图形的 x/y 位置现在等于 0x0。通读一下Painting in AWT and Swing为了更好的解释,但基本上,这意味着,你的绘画区域的左上角现在是 0x0。
  3. 您似乎认为文本是从第一个字符的左上角绘制的。这其实是错误的。文本沿着其基线绘制。您需要通过 Font 调整 y 位置来对此进行补偿。 s 上升值。

.

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) {
}

}

}

您遇到的问题都不是 super 严重的(当然,您的程序没有执行您想要的操作)并且表明您已经达到了代码能力的顶峰时刻。我这么说是因为我犯了完全相同的错误......;)

仔细看看2D GraphicsCustom Painting

我还想看看Code Conventions for the Java Programming Language因为如果你不关注别人,你只会惹恼他们;)

关于java - 自定义 JComponent 拒绝绘制(如果添加到 ArrayList),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15645923/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com