首页 > 解决方案 > 在对象的对象属性之间传递数据

问题描述

目前正在尝试用 JAVA 制作图形时钟,我正在处理元素之间的“通信”问题。事实上,我的架构在下面是可见的,由 3 个类组成:

在此处输入图像描述

通过将涉及数据(仅允许存储当前时间的时钟类)和图形(JFrame 以及clockPanel)的各种元素分组,抽屉被用作“容器”。

ClockPanel 是应该允许绘制时钟的类(目前我能够绘制静态元素,如下所示)。

在此处输入图像描述

我的问题是如何将时钟数据传递给 ClockPanel 以绘制时钟指针。

我正在考虑将时钟传递给 ClockPanel,但很明显这不是选择的解决方案,它会使抽屉变得无用。

所以我看不出如何在这两个元素之间建立联系。我尽量保持干净,以便为未来获得最好的反应。

我想了一会儿,我目前的结构完全错误,这导致了我的问题。

下面是来自抽屉和clockPanel的paintComponent函数的代码片段:

public void initDraw() {
        clockWindow = new JFrame();

        clockWindow.setTitle(getTitle());//Définit un titre pour notre fenêtre
        clockWindow.setSize(getSize(), getSize());//Définit sa taille, elle sera carrée car deux fois size en W et H
        clockWindow.setLocationRelativeTo(null);//Nous demandons maintenant à notre objet de se positionner au centre
        clockWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //Termine le processus lorsqu'on clique sur la croix rouge
        clockWindow.setResizable(false);//L'utilisateur ne peux pas redimensionner la fenetre
        clockWindow.setVisible(true);//Et enfin, la rendre visible

        clockPanel =  new ClockPanel(m_clock);
        clockWindow.setContentPane(clockPanel);

}
public void paintComponent(Graphics g){
        super.paintComponent(g);

        m_radiusWhiteCircle = (getWidth()/2)-40; //on prend un rayon qui va donner un cercle qui prend quasiment toute la fenetre
        m_centerX = m_centerY = getWidth()/2; //dans le contexte actuel, la fenetre est carrée, donc qu'on prenne widh ou height c'est pareil (a separe en deux opération si on change)
        System.out.println(getHeight());

        this.setBackground(new Color(160, 196, 235)); //on défini le fond du JPanel
        g.setColor(Color.BLACK);// le prochaine cercle sera noir
        int[] blackCircleSquare = convertCircleCoordsToSquareCoords(m_centerX, m_centerY, m_radiusWhiteCircle + 10); //on convertit les coordonées de notre cercle afin d'obtenir ceux du coin gauche du carré qui va contenri notre cerle
        g.fillOval(blackCircleSquare[0],blackCircleSquare[1],blackCircleSquare[2],blackCircleSquare[2]);//On dessine le contour de l'horlorge en prenant le centre de la fenetre et un rayon un peu supérieur au cercle "principal"

        g.setColor(Color.WHITE);//le prochain cercle sera blanc
        int[] whiteCircleSquare = convertCircleCoordsToSquareCoords(m_centerX, m_centerY, m_radiusWhiteCircle);
        g.fillOval(whiteCircleSquare[0],whiteCircleSquare[1],whiteCircleSquare[2],whiteCircleSquare[2]);

        g.setColor(Color.GREEN);
        int[] greenCircleSquare = convertCircleCoordsToSquareCoords(m_centerX, m_centerY, 10);
        g.fillOval(greenCircleSquare[0],greenCircleSquare[1],greenCircleSquare[2],greenCircleSquare[2]);

        g.setColor(Color.RED);
        g.setFont(new Font("TimesRoman", Font.PLAIN,20));
        for(int i=1;i<=12;i++) {
            int xHour = (int)(m_centerX+(m_radiusWhiteCircle-15)*Math.cos(i*INVARIABLE_ANGLE_HOUR - INVARIABLE_DECALAGE));
            int yHour = (int)(m_centerY+(m_radiusWhiteCircle-20)*Math.sin(i*INVARIABLE_ANGLE_HOUR - INVARIABLE_DECALAGE));
            g.drawString(String.valueOf(i),xHour,yHour);
        }
}

标签: javaswingoopobjectgraphics

解决方案


在我看来,以下步骤:

  1. 您可以使用已经存在的类进行时间处理(java.time包中的类)。我知道它可能乍一看似乎比手工课更复杂Clock,但它更有潜力。从长远来看,您可能会被迫了解它,因为您需要这种潜力。我们有更多的机会让将来维护我们代码的其他人知道已经存在的 API,而不是我们自己的手工类。而且,通过现在学习它,您现在也可以开始使用它。
  2. 至于类图,我认为可以说对象是:时间、时间的图形表示和一个窗口(具有时间的图形表示)。因此,这将导致我为Icon时间的图形表示子类化 an,使用已经存在的时间处理类(或者当且仅当它们不存在时才创建它们),最后是窗口(它已经作为 存在JFrame)。
  3. 那么,如何向Icon窗口提供一个?...通过一个JLabel.
  4. 然后创建一个Timer对象以JLabel每隔一段时间(根据需要)更新 的时钟图标/表示。

以下示例演示代码:

import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.time.LocalTime;
import javax.swing.Icon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

public class Main {

    public static class ClockIcon implements Icon {
        @Override
        public void paintIcon(final Component c, final Graphics g, final int x, final int y) {
            //The clock's painting goes here...
            g.fillOval(x, y, getIconWidth() - 1, getIconHeight() - 1);
            g.setColor(Color.CYAN.darker());
            g.drawString(LocalTime.now().toString(), x + 14, y + 5 + getIconHeight() / 2);
        }

        @Override
        public int getIconWidth() {
            return 100; //The clock's width goes here...
        }

        @Override
        public int getIconHeight() {
            return 100; //The clock's height goes here...
        }
    }

    public static void main(final String[] args) {
        SwingUtilities.invokeLater(() -> {

            final JLabel label = new JLabel(new ClockIcon(), SwingConstants.CENTER);

            final Timer engine = new Timer(500, e -> label.repaint());
            engine.setRepeats(true);
            engine.start();

            final JFrame frame = new JFrame("Clock");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.getContentPane().add(label);
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        });
    }
}

对于如何使用时间类的简单教程,我建议这样做。如果你更好奇,可以从这里的包文档开始。

希望能帮助到你。

一些注意事项:如果它对您没有您想要的帮助,我建议您不要急于接受/我的回答。请随时在评论中首先要求澄清,或者只是等待更多时间让更多有信誉的来源回答您的问题。我的观点是,在您的情况下,您没有复杂的类图可以使用:只需子类Icon并将其提供给 aJLabel和 a Timer。最后,我应该说,在您尝试过的问题中发布MRE有助于获得更好的答案。


推荐阅读