0

这是应该绘制 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);
  }
}
  1. 这不会导致任何结果 - JComponents 被创建并至少正确添加到 ArrayList,并且它的 paintComponent 方法运行,以及计时器事件,当倒计时达到 0 时,组件也至少从 ArrayList 中正确删除,但没有t 画任何东西,我不知道为什么。

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

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

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

4

1 回答 1

3

您的项目对 Swing 中的绘画工作方式存在许多非常基本的误解。

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

您的期望是 的内容窗格JFrame正在使用null布局。我发现很难看出您将如何管理它并在框架上安装其他组件。在任何情况下,我都会隔离一个单独的容器来充当您的Pocitadlo. 这允许您继续使用布局管理器来管理其他组件。

我有点担心您将整个Pocitadlo生成代码困在一个try-catch简单的捕获数字转换中。由于您已经应用了默认值,因此可以合理地自行捕获转换try-catch并在失败时忽略它(根据需要显示消息)。现在我是从外面进来的,所以你可能会看到需要这个,它刚刚引起了我的注意......

您的valueTimer actionPerformed代码略有错误,因为blinkTimer即使在完成后也有可能继续运行valueTimerif我通过将你们中的两个语句合并为一个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();
}

我个人会使用 a JPanelover a JComponentJPanel一开始是不透明的。

主要问题在于你的paintComponent方法。

  1. 您应该始终调用super.paintComponent,并且在不透明的组件上应该首先调用它。
  2. 例如,您似乎认为您必须在绘画时纠正组件位置g.fillRect(getX(), getY(), getWidth(), getHeight());。这实际上是错误的。图形上下文已被转换,因此组件/图形的 x/y 位置现在等于 0x0。阅读AWT 和 Swing中的绘画以获得更好的解释,但基本上,这意味着绘画区域的上/左角现在是 0x0。
  3. 您似乎认为文本是从第一个字符的上/左角绘制的。这实际上是错误的。文本沿其基线绘制。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 图形自定义绘画

我还会看看Java 编程语言的代码约定,因为如果你不遵守它们,你只会惹恼别人;)

于 2013-03-27T00:32:06.377 回答