在对象之间传递数据:通过对象的属性。

huangapple go评论106阅读模式
英文:

Passing data between objects attributes of an object

问题

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

在对象之间传递数据:通过对象的属性。

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

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

在对象之间传递数据:通过对象的属性。

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

我曾考虑将时钟传递给ClockPanel,但很明显这不是选择的解决方案,这会使绘图器变得无用。

因此,我无法看到如何在这两个元素之间建立联系。
我尽量保持清晰,以便为将来获得尽可能好的反应。

我曾经认为我的当前结构完全错误,这是导致我的问题的原因。

以下是绘图器和clockPanel的paintComponent函数中的代码片段:

  1. public void initDraw() {
  2. clockWindow = new JFrame();
  3. clockWindow.setTitle(getTitle());//定义窗口标题
  4. clockWindow.setSize(getSize(), getSize());//定义大小,因为宽和高都是size的两倍,所以窗口是正方形的
  5. clockWindow.setLocationRelativeTo(null);//将窗口定位在中心
  6. clockWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //点击红色交叉按钮时终止进程
  7. clockWindow.setResizable(false);//用户无法调整窗口大小
  8. clockWindow.setVisible(true);//最后,使其可见
  9. clockPanel = new ClockPanel(m_clock);
  10. clockWindow.setContentPane(clockPanel);
  11. }
  1. public void paintComponent(Graphics g){
  2. super.paintComponent(g);
  3. m_radiusWhiteCircle = (getWidth()/2)-40; //我们取一个半径,它会得到一个几乎填满整个窗口的圆
  4. m_centerX = m_centerY = getWidth()/2; //在当前情况下,窗口是正方形的,所以无论是widh还是height都是一样的(如果我们改变了就要分开计算)
  5. System.out.println(getHeight());
  6. this.setBackground(new Color(160, 196, 235)); //我们定义JPanel的背景色
  7. g.setColor(Color.BLACK);//下一个圆将是黑色的
  8. int[] blackCircleSquare = convertCircleCoordsToSquareCoords(m_centerX, m_centerY, m_radiusWhiteCircle + 10); //将我们圆的坐标转换为正方形的左上角坐标,它将包含我们的圆
  9. g.fillOval(blackCircleSquare[0],blackCircleSquare[1],blackCircleSquare[2],blackCircleSquare[2]);//我们画出时钟的轮廓,取窗口中心和稍大一点的半径
  10. g.setColor(Color.WHITE);//下一个圆是白色的
  11. int[] whiteCircleSquare = convertCircleCoordsToSquareCoords(m_centerX, m_centerY, m_radiusWhiteCircle);
  12. g.fillOval(whiteCircleSquare[0],whiteCircleSquare[1],whiteCircleSquare[2],whiteCircleSquare[2]);
  13. g.setColor(Color.GREEN);
  14. int[] greenCircleSquare = convertCircleCoordsToSquareCoords(m_centerX, m_centerY, 10);
  15. g.fillOval(greenCircleSquare[0],greenCircleSquare[1],greenCircleSquare[2],greenCircleSquare[2]);
  16. g.setColor(Color.RED);
  17. g.setFont(new Font("TimesRoman", Font.PLAIN,20));
  18. for(int i=1;i<=12;i++) {
  19. int xHour = (int)(m_centerX+(m_radiusWhiteCircle-15)*Math.cos(i*INVARIABLE_ANGLE_HOUR - INVARIABLE_DECALAGE));
  20. int yHour = (int)(m_centerY+(m_radiusWhiteCircle-20)*Math.sin(i*INVARIABLE_ANGLE_HOUR - INVARIABLE_DECALAGE));
  21. g.drawString(String.valueOf(i),xHour,yHour);
  22. }
  23. }
英文:

Currently trying to make a graphic clock in JAVA, I'm dealing with a problem of "communication" between elements. Indeed, my architecture is visible underneath and is composed of 3 classes:

在对象之间传递数据:通过对象的属性。

The drawer is used as a "container" by grouping the various elements which concern the data (the clock class which only allows to store the current time) and the graphic (the JFrame as well as clockPanel).

ClockPanel is the class that should allow to draw the clock (for the moment I was able to draw the static elements, as visible below).

在对象之间传递数据:通过对象的属性。

My problem is how to pass the clock data to ClockPanel in order to draw the clock hands.

I was thinking of passing the clock to ClockPanel but it seems pretty obvious that this is not the solution to choose, it would make the drawer useless.

So I can't see how to make the link between these two elements.
I try to be as clean as possible in order to acquire the best possible reflexes for the future.

I thought for a while that my current structure is completely wrong, which is causing my problem.

Below are code snippets from the drawer and the paintComponent function of the clockPanel:

  1. public void initDraw() {
  2. clockWindow = new JFrame();
  3. clockWindow.setTitle(getTitle());//D&#233;finit un titre pour notre fen&#234;tre
  4. clockWindow.setSize(getSize(), getSize());//D&#233;finit sa taille, elle sera carr&#233;e car deux fois size en W et H
  5. clockWindow.setLocationRelativeTo(null);//Nous demandons maintenant &#224; notre objet de se positionner au centre
  6. clockWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //Termine le processus lorsqu&#39;on clique sur la croix rouge
  7. clockWindow.setResizable(false);//L&#39;utilisateur ne peux pas redimensionner la fenetre
  8. clockWindow.setVisible(true);//Et enfin, la rendre visible
  9. clockPanel = new ClockPanel(m_clock);
  10. clockWindow.setContentPane(clockPanel);
  11. }
  1. public void paintComponent(Graphics g){
  2. super.paintComponent(g);
  3. m_radiusWhiteCircle = (getWidth()/2)-40; //on prend un rayon qui va donner un cercle qui prend quasiment toute la fenetre
  4. m_centerX = m_centerY = getWidth()/2; //dans le contexte actuel, la fenetre est carr&#233;e, donc qu&#39;on prenne widh ou height c&#39;est pareil (a separe en deux op&#233;ration si on change)
  5. System.out.println(getHeight());
  6. this.setBackground(new Color(160, 196, 235)); //on d&#233;fini le fond du JPanel
  7. g.setColor(Color.BLACK);// le prochaine cercle sera noir
  8. int[] blackCircleSquare = convertCircleCoordsToSquareCoords(m_centerX, m_centerY, m_radiusWhiteCircle + 10); //on convertit les coordon&#233;es de notre cercle afin d&#39;obtenir ceux du coin gauche du carr&#233; qui va contenri notre cerle
  9. g.fillOval(blackCircleSquare[0],blackCircleSquare[1],blackCircleSquare[2],blackCircleSquare[2]);//On dessine le contour de l&#39;horlorge en prenant le centre de la fenetre et un rayon un peu sup&#233;rieur au cercle &quot;principal&quot;
  10. g.setColor(Color.WHITE);//le prochain cercle sera blanc
  11. int[] whiteCircleSquare = convertCircleCoordsToSquareCoords(m_centerX, m_centerY, m_radiusWhiteCircle);
  12. g.fillOval(whiteCircleSquare[0],whiteCircleSquare[1],whiteCircleSquare[2],whiteCircleSquare[2]);
  13. g.setColor(Color.GREEN);
  14. int[] greenCircleSquare = convertCircleCoordsToSquareCoords(m_centerX, m_centerY, 10);
  15. g.fillOval(greenCircleSquare[0],greenCircleSquare[1],greenCircleSquare[2],greenCircleSquare[2]);
  16. g.setColor(Color.RED);
  17. g.setFont(new Font(&quot;TimesRoman&quot;, Font.PLAIN,20));
  18. for(int i=1;i&lt;=12;i++) {
  19. int xHour = (int)(m_centerX+(m_radiusWhiteCircle-15)*Math.cos(i*INVARIABLE_ANGLE_HOUR - INVARIABLE_DECALAGE));
  20. int yHour = (int)(m_centerY+(m_radiusWhiteCircle-20)*Math.sin(i*INVARIABLE_ANGLE_HOUR - INVARIABLE_DECALAGE));
  21. g.drawString(String.valueOf(i),xHour,yHour);
  22. }
  23. }

答案1

得分: 1

在我看来,以下是步骤:

  1. 您可以使用已存在的时间处理类(位于 java.time 包中的类)。我知道乍一看可能比手工编写的 Clock 类更复杂,但它具有更大的潜力。从长远来看,您可能会被迫学习它,因为您将需要这种潜力。未来维护我们代码的其他人更有机会了解已存在的 API,而不是我们自己手工编写的类。而且,通过现在学习,您也可以立即开始使用它。
  2. 至于类图,我认为可以说对象是:时间、时间的图形表示以及窗口(具有时间的图形表示)。因此,这会引导我为时间的图形表示子类化一个 Icon,使用已存在的时间处理类(如果它们不存在,则仅在此情况下创建),最后窗口(已存在为 JFrame)。
  3. 那么,如何将 Icon 提供给窗口呢?... 通过一个 JLabel
  4. 然后创建一个 Timer 对象,以便根据需要定期更新 JLabel 的时钟图标/表示。

以下是演示代码示例:

  1. import java.awt.Color;
  2. import java.awt.Component;
  3. import java.awt.Graphics;
  4. import java.time.LocalTime;
  5. import javax.swing.Icon;
  6. import javax.swing.JFrame;
  7. import javax.swing.JLabel;
  8. import javax.swing.SwingConstants;
  9. import javax.swing.SwingUtilities;
  10. import javax.swing.Timer;
  11. public class Main {
  12. public static class ClockIcon implements Icon {
  13. @Override
  14. public void paintIcon(final Component c, final Graphics g, final int x, final int y) {
  15. // 时钟的绘制在此处...
  16. g.fillOval(x, y, getIconWidth() - 1, getIconHeight() - 1);
  17. g.setColor(Color.CYAN.darker());
  18. g.drawString(LocalTime.now().toString(), x + 14, y + 5 + getIconHeight() / 2);
  19. }
  20. @Override
  21. public int getIconWidth() {
  22. return 100; // 时钟的宽度在此处...
  23. }
  24. @Override
  25. public int getIconHeight() {
  26. return 100; // 时钟的高度在此处...
  27. }
  28. }
  29. public static void main(final String[] args) {
  30. SwingUtilities.invokeLater(() -> {
  31. final JLabel label = new JLabel(new ClockIcon(), SwingConstants.CENTER);
  32. final Timer engine = new Timer(500, e -> label.repaint());
  33. engine.setRepeats(true);
  34. engine.start();
  35. final JFrame frame = new JFrame("Clock");
  36. frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  37. frame.getContentPane().add(label);
  38. frame.pack();
  39. frame.setLocationRelativeTo(null);
  40. frame.setVisible(true);
  41. });
  42. }
  43. }

关于如何使用时间类的简单教程,我建议您参考这里。如果您更加好奇,您可以从这里开始阅读该包的文档。

希望对您有所帮助。

一些建议:如果我的答案没有像您希望的那样帮助您,我建议您不要急于接受答案。您可以在评论中首先要求澄清,或者只是等待更多时间以获取更有声望的来源来回答您的问题。我认为在您的情况下,您没有一个复杂的类图要处理:只需为 Icon 创建子类,然后将其提供给 JLabelTimer。最后,我还应该说,将您尝试过的 最小可复现示例(MRE) 发布在问题中可以帮助获得更好的答案。

英文:

In my opinion, the following steps:

  1. You can use the classes already existing for time handling (classes in java.time package). I know it might at a glance seem more complex than the handmade class Clock, but it has more potential. In the long run, you may be forced to learn about it because you will need that potential. We have more chances someone else, who will maintain our code in the future, to know about the already existing API and not our own handmade classes. And also, by learning it now, you can also start using it now.
  2. As for the class diagram, I think one can say that the objects are: time, graphical representation of time and a window (having a graphical representation of time). So that would lead me to subclass an Icon for the graphical representation of the time, use the already existing time handling classes (or create them if, and only if, they did not already exist) and finally the window (which already exists as JFrame).
  3. So, how to supply an Icon to the window?... Via a JLabel.
  4. Then create a Timer object to update the JLabel's clock icon/representation every so often (as needed).

Follows example demonstrating code:

  1. import java.awt.Color;
  2. import java.awt.Component;
  3. import java.awt.Graphics;
  4. import java.time.LocalTime;
  5. import javax.swing.Icon;
  6. import javax.swing.JFrame;
  7. import javax.swing.JLabel;
  8. import javax.swing.SwingConstants;
  9. import javax.swing.SwingUtilities;
  10. import javax.swing.Timer;
  11. public class Main {
  12. public static class ClockIcon implements Icon {
  13. @Override
  14. public void paintIcon(final Component c, final Graphics g, final int x, final int y) {
  15. //The clock&#39;s painting goes here...
  16. g.fillOval(x, y, getIconWidth() - 1, getIconHeight() - 1);
  17. g.setColor(Color.CYAN.darker());
  18. g.drawString(LocalTime.now().toString(), x + 14, y + 5 + getIconHeight() / 2);
  19. }
  20. @Override
  21. public int getIconWidth() {
  22. return 100; //The clock&#39;s width goes here...
  23. }
  24. @Override
  25. public int getIconHeight() {
  26. return 100; //The clock&#39;s height goes here...
  27. }
  28. }
  29. public static void main(final String[] args) {
  30. SwingUtilities.invokeLater(() -&gt; {
  31. final JLabel label = new JLabel(new ClockIcon(), SwingConstants.CENTER);
  32. final Timer engine = new Timer(500, e -&gt; label.repaint());
  33. engine.setRepeats(true);
  34. engine.start();
  35. final JFrame frame = new JFrame(&quot;Clock&quot;);
  36. frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  37. frame.getContentPane().add(label);
  38. frame.pack();
  39. frame.setLocationRelativeTo(null);
  40. frame.setVisible(true);
  41. });
  42. }
  43. }

For a simple tutorial on how to use the time classes I would suggest this. If you are more curious, you can start at the documentation of the package here.

Hope it helps.

Some notes: I would suggest you to not be in a hurry of accepting an/my answer if it does not help you as much as you wanted. Feel free to ask first for clarifications in the comments or simply wait more time for more reputable sources to answer your question. My opinion is that in your case you don't have a complex class diagram to work with: just subclass Icon and give this to a JLabel and a Timer. Finally, I should say that, posting an MRE in the question, of what you tried, helps getting better answers.

huangapple
  • 本文由 发表于 2020年4月9日 22:21:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/61123351.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定