- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
由于 Java 只支持单继承
,我希望直接在 JPanel
的实例上绘制
,它是类 面板
。我从成员那里获取了一个 Graphics
的实例,然后在上面绘制我想要的任何东西。
我怎么能不继承 JComponent
或 JPanel
并仍然利用 getGraphics()
在 this
上绘画不覆盖 public void paintComponent(Graphics g)
?
private class Panel {
private JPanel panel;
private Graphics g;
public Panel() {
panel = new JPanel();
}
public void draw() {
g = panel.getGraphics();
g.setColor(Color.CYAN);
g.draw(Some Component);
panel.repaint();
}
}
面板被添加到一个 JFrame
中,在调用 panel.draw()
之前它是可见的。这种方法对我不起作用,虽然我已经知道如何通过继承 JPanel
并覆盖 public void paintComponent(Graphics g)
来绘制自定义组件,但我不想从 JPanel
继承。
最佳答案
这里有一些非常简单的示例,展示了如何在 paintComponent
之外进行绘制。
绘图实际上发生在 java.awt.image.BufferedImage
上,我们可以在任何地方执行此操作,只要我们在事件调度线程上即可。 (有关 Swing 多线程的讨论,请参阅 here 和 here。)
然后,我将覆盖 paintComponent
,但只是将图像绘制到面板上。 (我还在角落里画了一点色板。)
这样绘图实际上是永久性的,并且 Swing 可以在需要时重新绘制面板而不会给我们带来问题。如果需要,我们还可以轻松地将图像保存到文件中。
import javax.swing.*;
import java.awt.*;
import java.awt.image.*;
import java.awt.event.*;
/**
* Holding left-click draws, and
* right-clicking cycles the color.
*/
class PaintAnyTime {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new PaintAnyTime();
}
});
}
Color[] colors = {Color.red, Color.blue, Color.black};
int currentColor = 0;
BufferedImage img = new BufferedImage(256, 256, BufferedImage.TYPE_INT_ARGB);
Graphics2D imgG2 = img.createGraphics();
JFrame frame = new JFrame("Paint Any Time");
JPanel panel = new JPanel() {
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
// Creating a copy of the Graphics
// so any reconfiguration we do on
// it doesn't interfere with what
// Swing is doing.
Graphics2D g2 = (Graphics2D) g.create();
// Drawing the image.
int w = img.getWidth();
int h = img.getHeight();
g2.drawImage(img, 0, 0, w, h, null);
// Drawing a swatch.
Color color = colors[currentColor];
g2.setColor(color);
g2.fillRect(0, 0, 16, 16);
g2.setColor(Color.black);
g2.drawRect(-1, -1, 17, 17);
// At the end, we dispose the
// Graphics copy we've created
g2.dispose();
}
@Override
public Dimension getPreferredSize() {
return new Dimension(img.getWidth(), img.getHeight());
}
};
MouseAdapter drawer = new MouseAdapter() {
boolean rButtonDown;
Point prev;
@Override
public void mousePressed(MouseEvent e) {
if (SwingUtilities.isLeftMouseButton(e)) {
prev = e.getPoint();
}
if (SwingUtilities.isRightMouseButton(e) && !rButtonDown) {
// (This just behaves a little better
// than using the mouseClicked event.)
rButtonDown = true;
currentColor = (currentColor + 1) % colors.length;
panel.repaint();
}
}
@Override
public void mouseDragged(MouseEvent e) {
if (prev != null) {
Point next = e.getPoint();
Color color = colors[currentColor];
// We can safely paint to the
// image any time we want to.
imgG2.setColor(color);
imgG2.drawLine(prev.x, prev.y, next.x, next.y);
// We just need to repaint the
// panel to make sure the
// changes are visible
// immediately.
panel.repaint();
prev = next;
}
}
@Override
public void mouseReleased(MouseEvent e) {
if (SwingUtilities.isLeftMouseButton(e)) {
prev = null;
}
if (SwingUtilities.isRightMouseButton(e)) {
rButtonDown = false;
}
}
};
PaintAnyTime() {
// RenderingHints let you specify
// options such as antialiasing.
imgG2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
imgG2.setStroke(new BasicStroke(3));
//
panel.setBackground(Color.white);
panel.addMouseListener(drawer);
panel.addMouseMotionListener(drawer);
Cursor cursor =
Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR);
panel.setCursor(cursor);
frame.setContentPane(panel);
frame.pack();
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
也可以用 ImageIcon
设置一个 JLabel
,尽管我个人不喜欢这种方法。我不认为 JLabel
和 ImageIcon
的规范要求在我们将图像传递给构造函数后查看我们对图像所做的更改。
这种方式也不允许我们做像绘制样本这样的事情。 (对于稍微复杂一点的绘画程序,例如 MSPaint,我们希望有一种方法来选择一个区域并在其周围绘制一个边界框。这是我们希望能够直接在其上绘画的另一个地方面板,除了绘制图像。)
import javax.swing.*;
import java.awt.*;
import java.awt.image.*;
import java.awt.event.*;
/**
* Holding left-click draws, and
* right-clicking cycles the color.
*/
class PaintAnyTime {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new PaintAnyTime();
}
});
}
Color[] colors = {Color.red, Color.blue, Color.black};
int currentColor = 0;
BufferedImage img = new BufferedImage(256, 256, BufferedImage.TYPE_INT_ARGB);
Graphics2D imgG2 = img.createGraphics();
JFrame frame = new JFrame("Paint Any Time");
JLabel label = new JLabel(new ImageIcon(img));
MouseAdapter drawer = new MouseAdapter() {
boolean rButtonDown;
Point prev;
@Override
public void mousePressed(MouseEvent e) {
if (SwingUtilities.isLeftMouseButton(e)) {
prev = e.getPoint();
}
if (SwingUtilities.isRightMouseButton(e) && !rButtonDown) {
// (This just behaves a little better
// than using the mouseClicked event.)
rButtonDown = true;
currentColor = (currentColor + 1) % colors.length;
label.repaint();
}
}
@Override
public void mouseDragged(MouseEvent e) {
if (prev != null) {
Point next = e.getPoint();
Color color = colors[currentColor];
// We can safely paint to the
// image any time we want to.
imgG2.setColor(color);
imgG2.drawLine(prev.x, prev.y, next.x, next.y);
// We just need to repaint the
// label to make sure the
// changes are visible
// immediately.
label.repaint();
prev = next;
}
}
@Override
public void mouseReleased(MouseEvent e) {
if (SwingUtilities.isLeftMouseButton(e)) {
prev = null;
}
if (SwingUtilities.isRightMouseButton(e)) {
rButtonDown = false;
}
}
};
PaintAnyTime() {
// RenderingHints let you specify
// options such as antialiasing.
imgG2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
imgG2.setStroke(new BasicStroke(3));
//
label.setPreferredSize(new Dimension(img.getWidth(), img.getHeight()));
label.setBackground(Color.white);
label.setOpaque(true);
label.addMouseListener(drawer);
label.addMouseMotionListener(drawer);
Cursor cursor =
Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR);
label.setCursor(cursor);
frame.add(label, BorderLayout.CENTER);
frame.pack();
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
关于Java JPanel getGraphics() 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21322353/
在 drawToScreen 方法内调用 getGraphics() 时,我的 JPanel 预览返回 null。 Test 类也扩展了 JPanel,因为它被保存在 TabbedPane 中。该类还
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我正在尝试在扩展了 JComponent 类的地方呈现自定义 Swing 组件。 为了简化组件需求,让我们将我的组件总结为需要渲染几个字符串,每个字符串都有自己的字体。 我需要我的组件的大小完全符合我
我的应用程序看起来像这样,我在 draw() 方法中遇到空指针异常,准确地说是在 g.drawImage(img, 0, 0, null) 处 package com.ochs.game; impor
我正在做一个选择工具,我已经提供了这些解决方案,在第一个使用 JPanel getGraphics 方法中,我在鼠标拖动的地方绘制一个椭圆形,在第二个中,我重写 PaintComponent 方法来绘
我有一个带有 JPanel 和 PaintComponent() 的类。我还有一个实现 Runnable 的类,我计划在线程启动后将图像绘制到 PaintComponent 上。我的构造函数接收 JP
嗨,我是 java GUI 编程新手。我创建了 Jframe(MainFrame) 并添加了 JPanel(OutPanel),其中还有另一个 Jpanel(InnerPanel)。我尝试在 Inne
我开始学习用 Java 创建游戏,我使用的其中一种方法包括 BufferedImage。这是我得到的错误: "Exception in thread "main" java.lang.NullPoin
由于 Java 只支持单继承,我希望直接在 JPanel 的实例上绘制,它是类 面板。我从成员那里获取了一个 Graphics 的实例,然后在上面绘制我想要的任何东西。 我怎么能不继承 JCompon
我有底部导航,我也替换了 标记为 FragmentContainerView它给了我关于它没有设置 NavController 的错误,然后我被发布 this问题并解决了问题,但是当方向更改并在底部导
我想知道出了什么问题。我以前曾这样做过,但由于某种原因,这次我无法让它发挥作用。 我在 Netbeans 中设计了该项目。最相关的部分是 initTiras 方法,它应该绘制一些东西,但它没有。我包含
我正在尝试一个充当按钮但使用图像进行显示的对象。我的问题是,当调用 getGraphics() 时,它返回 null。我到处找也没找到原因? 我的构造函数的代码是...... public class
我在这里遇到了一些困难。我在尝试解决这个问题时在其他地方读到,你永远不应该 getGraphics()。问题是,我无法使用 Paint()/PaintComponent() 方法提供的 Graphic
下面是代码(我在这个类中扩展了 JFrame)(Point 'size' 是屏幕的大小): setVisible(true); backBuffer = createImage(size.x, siz
public void saveImage(String path){ BufferedImage image = (BufferedImage) createImage(500, 500);
如果我正在使用 JPanel,getGraphics 返回的 Graphics 对象与在 paintComponent 方法中传递的 Graphics 对象有什么区别? 最佳答案 getGraphic
我在调用 BufferedImage.getGraphics() 方法的某些框架 API 时遇到问题,从而导致内存泄漏。这个方法的作用是它总是调用 BufferedImage.createGraphi
如何在没有类(扩展 JFrame)的情况下绘制对象?我找到了 getGraphics 方法,但它没有绘制对象。 import javax.swing.*; import java.awt.*; pub
(这是 previous 问题的后续) 将 BufferedImage 从一种类型转换为另一种类型或制作副本的标准推荐方法是使用 getGraphics().drawImage() ( example
MadProgrammer 发表了评论here声明您永远不应该使用 Component.getGraphics,我普遍同意这一点:在几乎所有情况下,它都是错误的。 但以我多年前创建的这个类为例。我正在
我是一名优秀的程序员,十分优秀!