java - 在对象的对象属性之间传递数据
问题描述
目前正在尝试用 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);
}
}
解决方案
在我看来,以下步骤:
- 您可以使用已经存在的类进行时间处理(
java.time
包中的类)。我知道它可能乍一看似乎比手工课更复杂Clock
,但它更有潜力。从长远来看,您可能会被迫了解它,因为您需要这种潜力。我们有更多的机会让将来维护我们代码的其他人知道已经存在的 API,而不是我们自己的手工类。而且,通过现在学习它,您现在也可以开始使用它。 - 至于类图,我认为可以说对象是:时间、时间的图形表示和一个窗口(具有时间的图形表示)。因此,这将导致我为
Icon
时间的图形表示子类化 an,使用已经存在的时间处理类(或者当且仅当它们不存在时才创建它们),最后是窗口(它已经作为 存在JFrame
)。 - 那么,如何向
Icon
窗口提供一个?...通过一个JLabel
. - 然后创建一个
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有助于获得更好的答案。
推荐阅读
- java - 如何让 Java 程序从 iOS 应用程序中获取输入
- c# - 打开已经打开的表单而不丢失数据
- postgresql - Postgresql 数组函数不使用索引
- ruby-on-rails - Ruby on Rails 在 Blogspot 上运行?
- python - 从列表理解中获得一个集合。Python
- android - 无法从 Android SQLite 检索保存的数据
- jquery - 在 SPA 中更改 Facebook 元标记,但共享时无法识别 OG 元标记更改
- php - PHP HTTP Header 多次出现并显示相同的消息
- javascript - 未指定表的 SELECT * 无效
- java - 如何对具有覆盖率的 void 函数执行单元测试