将自定义 Swing 组件的绘制委托给 parent
Delegate painting of custom Swing component to parent
我的目标
我希望我的自定义 Swing 组件 CellLabel extends JLabel
始终绘制某些东西 (X),而某些其他元素 (Y) 仅当其 parent -(JPanel
保持 一个 CellLabel
s) 的网格 - 告诉它。 (Y) 的绘制取决于网格中相邻单元格的状态,只有 JPanel
可以获取此信息并决定是否 以及如何 (Y)为每个 child CellLabel
.
绘制
我的问题
我如何将绘画行为外部化(到一个带有参数的方法中,该方法允许我描述 如何 准确地绘制 (Y))绘画行为,以便 parent 可以决定是否要 CellLabel
child 绘制 (Y)?
我的问题
那里的每个 Swing 教程都告诉我在创建自定义组件时应该覆盖 paintComponent
方法;但是,在我的应用程序中,组件无法自行决定是否以及如何绘制 (Y),因为它缺少必要的信息。
我尝试编写一个 CellLabel::paintY(int offset)
方法,一旦它决定了如何以及是否绘制 (Y),我可以从 parent 调用它:
class CellLabel extends JLabel {
void paintComponent(Graphics g) {
super.paintComponent(g);
// Paint elements (X) which should always be painted, independent
// of external state
}
void paintY(int[] params){
Graphics2D g2 = (Graphics2D) this.getGraphics();
// Perform some calculation with params that decide how painting is done
// (*) Actually paint elements (Y) by using the g2 graphics context
}
}
但是,似乎我无法在约定告诉我覆盖的预定义 paint
方法之外获取 Graphics
上下文。我在 (*) 处遇到以下异常(实际尝试使用 g2 进行绘制时):
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at CellLabel.paintY(CellLabel.java:77)
at AutomatonUI.createAndShowGUI(AutomatonUI.java:50)
at AutomatonUI.access[=12=]0(AutomatonUI.java:22)
at AutomatonUI.run(AutomatonUI.java:29)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:744)
at java.awt.EventQueue.access0(EventQueue.java:97)
at java.awt.EventQueue.run(EventQueue.java:697)
at java.awt.EventQueue.run(EventQueue.java:691)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain.doIntersectionPrivilege(ProtectionDomain.java:75)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:714)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
我有丰富的业务逻辑编码经验和 number-crunching,但我对 Swing(和 UI 编程)总体来说还很陌生,所以请原谅(并教育我) ) 如果我做错了什么。
IIRC,您的 paintComponent 函数需要调用 super.paintComponent(g);
上次我用 swing 编写程序时,我在 class 中声明了一个静态图形对象,任何东西都可以访问(这可能是一件很糟糕的事情,但它是一个帮助我的解决方法来完成我的任务)。不是将信息存储在二维数组中,而是将 "information" 个对象存储在数组中。这些信息对象(例如对象 x)可以包含有关单元格本身的所有信息,以及一个 "draw(g)" 方法。该绘制方法可以指示如何绘制此单元格。在 paintComponent 函数中,您现在可以调用
//where g is the graphics object
for (array x : array of arrays) {
for (informationObject y : x) {
y.draw(g);
}
}
现在您可以在对象内部进行所有计算,而不必处理获取外部信息和在外部进行计算的问题。 (那么,代码也会更容易调试)
更好的方法可能是将您的逻辑与 Swing GUI 库分开。例如,定义一个 CellContainer
class 包含 Cell
对象,可以在每次渲染之前更新(在更新中你可以从 [=10= 更新 Cell
s ] 随心所欲)。然后你可以有 CellContainerPanel
和 CellLabel
class 扩展适当的 Swing class 引用 CellContainer
和 Cell
每个只是绘制他们的参考可用的状态。
我的目标
我希望我的自定义 Swing 组件 CellLabel extends JLabel
始终绘制某些东西 (X),而某些其他元素 (Y) 仅当其 parent -(JPanel
保持 一个 CellLabel
s) 的网格 - 告诉它。 (Y) 的绘制取决于网格中相邻单元格的状态,只有 JPanel
可以获取此信息并决定是否 以及如何 (Y)为每个 child CellLabel
.
我的问题
我如何将绘画行为外部化(到一个带有参数的方法中,该方法允许我描述 如何 准确地绘制 (Y))绘画行为,以便 parent 可以决定是否要 CellLabel
child 绘制 (Y)?
我的问题
那里的每个 Swing 教程都告诉我在创建自定义组件时应该覆盖 paintComponent
方法;但是,在我的应用程序中,组件无法自行决定是否以及如何绘制 (Y),因为它缺少必要的信息。
我尝试编写一个 CellLabel::paintY(int offset)
方法,一旦它决定了如何以及是否绘制 (Y),我可以从 parent 调用它:
class CellLabel extends JLabel {
void paintComponent(Graphics g) {
super.paintComponent(g);
// Paint elements (X) which should always be painted, independent
// of external state
}
void paintY(int[] params){
Graphics2D g2 = (Graphics2D) this.getGraphics();
// Perform some calculation with params that decide how painting is done
// (*) Actually paint elements (Y) by using the g2 graphics context
}
}
但是,似乎我无法在约定告诉我覆盖的预定义 paint
方法之外获取 Graphics
上下文。我在 (*) 处遇到以下异常(实际尝试使用 g2 进行绘制时):
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at CellLabel.paintY(CellLabel.java:77)
at AutomatonUI.createAndShowGUI(AutomatonUI.java:50)
at AutomatonUI.access[=12=]0(AutomatonUI.java:22)
at AutomatonUI.run(AutomatonUI.java:29)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:744)
at java.awt.EventQueue.access0(EventQueue.java:97)
at java.awt.EventQueue.run(EventQueue.java:697)
at java.awt.EventQueue.run(EventQueue.java:691)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain.doIntersectionPrivilege(ProtectionDomain.java:75)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:714)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
我有丰富的业务逻辑编码经验和 number-crunching,但我对 Swing(和 UI 编程)总体来说还很陌生,所以请原谅(并教育我) ) 如果我做错了什么。
IIRC,您的 paintComponent 函数需要调用 super.paintComponent(g);
上次我用 swing 编写程序时,我在 class 中声明了一个静态图形对象,任何东西都可以访问(这可能是一件很糟糕的事情,但它是一个帮助我的解决方法来完成我的任务)。不是将信息存储在二维数组中,而是将 "information" 个对象存储在数组中。这些信息对象(例如对象 x)可以包含有关单元格本身的所有信息,以及一个 "draw(g)" 方法。该绘制方法可以指示如何绘制此单元格。在 paintComponent 函数中,您现在可以调用
//where g is the graphics object
for (array x : array of arrays) {
for (informationObject y : x) {
y.draw(g);
}
}
现在您可以在对象内部进行所有计算,而不必处理获取外部信息和在外部进行计算的问题。 (那么,代码也会更容易调试)
更好的方法可能是将您的逻辑与 Swing GUI 库分开。例如,定义一个 CellContainer
class 包含 Cell
对象,可以在每次渲染之前更新(在更新中你可以从 [=10= 更新 Cell
s ] 随心所欲)。然后你可以有 CellContainerPanel
和 CellLabel
class 扩展适当的 Swing class 引用 CellContainer
和 Cell
每个只是绘制他们的参考可用的状态。