发布覆盖java中组件的paint方法

Posted

技术标签:

【中文标题】发布覆盖java中组件的paint方法【英文标题】:Post overriding the paint method of the components in java 【发布时间】:2016-03-14 22:17:07 【问题描述】:

在 java awt 或 swing 中,当您想要更改某些组件的绘制时,通常必须覆盖方法 paint(Graphics g)(在 awt)或 paintComponent(Graphics g)(在 swing 中)。 这通常(也许总是 - 我不确定)在您创建组件时完成,例如:

JPanel jPanel = new JPanel() 
                @Override
                protected void paintComponent(Graphics g) 

                    super.paintComponent(g);

                    Graphics2D g2d = (Graphics2D) g;
                    //... my implementation of paint, some transfromations, rotation, etc
                   

            ; 

想象一下,你有一个组件容器,例如可以由一些 JLabels、一些 JTextFields、一些图像组成。这将全部放在一个组件上。 通过容器,我的意思是您有一些带有 id 或类似结构的列表或映射,其中所有组件都将放在一个 JFrame 上。 问题是,我是否可以在使用此列表中的所有组件创建后,在所有组件都已创建的那一刻更改绘制方法。例如,我想做 Graphisc2D 中定义的旋转动作(rotate)。 所以基本上我想要的是我通过我拥有的组件列表并说: “列表中的所有人(组件)都将旋转某个角度”。那可能吗?如果是怎么办?

编辑: 这是我工作不正常的解决方案:

  graphicalDisplayPanel = new JPanel() 
                    @Override
                    protected void paintComponent(Graphics g) 

                        super.paintComponent(g);


                        g2d = (Graphics2D) g;
                        g2d.rotate(Math.PI, anchorx, anchory);


                    

                 @Override
                      public void paintChildren(Graphics g) 
                           super.paintChildren(g);
                           Graphics2D g2d2 = (Graphics2D) g;

                        g2d2.rotate(Math.PI, anchorx, anchory);

                      

                ;

    JFrame jFrame = JFrame();
    // ... setting dimension, position, visible etc for JFrame, it works correctly nonrotated

    jFrame.setContentPane(graphicalDisplayPanel);

【问题讨论】:

简单地说,是的,但请参阅answer。 @trashgod 谢谢,但是a)如果您阅读了我的问题,我问它是否可能在创建之后,但您的示例在创建期间执行。 b) 为什么不调用 super.paintComponent(g);在g2d的变化之前?? c)我之前确实这样做过,但问题是它在开始时会旋转它,但是如果您更改某些组件的值 - 例如显示在其上的文本。它再次呈现非旋转... @trashgod 请查看我的问题的编辑和我之前的评论,您可以看到与您的类似的解决方案以及我在问这个问题之前所做的解决方案。但它有我提到的问题。 完全正确;您可以rotate() 图形上下文重新定位像素,但AWT 和Swing 组件 被设计为直立使用。 如需尽快获得更好的帮助,请发帖minimal reproducible example 或Short, Self Contained, Correct Example。 【参考方案1】:

我没有对此进行测试,但它似乎可以工作。一个 JComponent 的 paint() 方法调用:

paintComponent(co);
paintBorder(co);
paintChildren(co);

其中 co 是一个图形对象。理论上,您创建一个图像,检索图形对象,然后将其传递给paintChildren()。如果您这样做,您将不得不自己致电paintComponent()paintBorder()。然后,只需旋转图像并将其绘制到您的组件中。您可能必须相应地裁剪图像或调整组件大小才能使其正常工作。它可能看起来像这样:

BufferedImage myImage;

@Override
public void paint(Graphics g)
    myImage = new BufferedImage(getWidth(), getHeight(), BufferedImage.TRANSLUCENT);
    //using a transparent BufferedImage might not be efficient in your case
    Graphics myGraphics = myImage.getGraphics();
    super.paintComponent(g);
    super.paintBorder(g);
    super.paintChildren(myGraphics);
    //rotation code here
    //  ...
    //draw children onto your component
    g.drawImage(myImage, 0, 0,getWidth(), getHeight(), null);


希望我没有犯任何错误,如果可行,请告诉我。

【讨论】:

图像的意义是什么?我想在放置它们的 contentPane 中心周围创建组件,为什么要使用一些图像? 你的问题有点混乱。当您说您想要“例如,我想要执行 Graphisc2D 中定义的所有旋转动作(旋转)。”时,我以为您想要旋转 contentPane 中的所有对象。 Edit图片的原因是为了让你可以旋转它。 是的,你是对的。但我可能只是没有真正得到带有图像的部分,或者我无法从代码中看到它,以为它可能在那里。如果我将通常放置在 contentPane 上的所有组件放置到您的图像上,然后将图像放置在 contentPane 上,我会很有意义。要正确理解旋转 - 所有组件的旋转中心都是内容窗格的中心。就像你拿监视器并手动旋转他一样。 我正在使用图像,以便获得可以使用的图形对象,例如缓冲区。您还可以使用它优化您的程序,因为您只需要在每次更改时重绘图像,而不是每次重绘发生时。 对不起,我仍然不明白你想用图像做什么。你用它来获取你用于paintChildren的mygraphics,我认为它实际上应该只是supper.paintChildren(g),然后有注释应该代表旋转它只是这2行:g2d =(Graphics2D)g; g2d.rotate(Math.PI, anchorx, anchory);加上计算中心点anchorx,anchory,这很容易(widht/2.0,height/2.0)最后你绘制图像,但上面什么都没有,它的空图像你只创建实例什么都不做。跨度> 【参考方案2】:

所以基本上我想要的是通过我拥有的组件列表并说:“列表中的所有人(组件)都将旋转某个角度”。

如果您想旋转面板并因此旋转面板上的所有组件作为一个单一的使用,那么您需要在 paintComponent() 方法中进行自定义绘制。

例如,如果您想旋转具有不同旋转角度的单个图像,那么您可以再次在 paintComponent(...) 方法中执行此操作并更改每个组件的角度。

或者,在第二种情况下,您可以使用Rotated Icon 类。在这种情况下,图标只是添加到 JLabel 中。然后你可以改变旋转的度数并重新绘制标签,这样就没有自定义绘制(除了图标本身)。

【讨论】:

由于没有人回答问题,但只是背景信息的事情我把真正的问题加粗了。如果我正确理解这个绘制组件是您必须在创建实例之前覆盖的方法。但是由于现有应用程序中所有组件的复杂创建机制,我询问当您已经拥有 List 并且所有组件都已创建并且您想要更改它们的旋转时,是否可以通过其他方式完成此操作。 注意:我认为它不可能覆盖已经存在的对象的方法,所以我不能在绘制组件中这样做。 @user1097772,问题已经得到解答。不,除非您覆盖绘画方法,否则您不能在将组件添加到 GUI 后旋转组件。或者除非您想创建一个“包装器面板”面板,以便从 GUI 中删除现有面板,然后将此面板添加到包装器面板,然后将包装器面板添加到 GUI。同样,这意味着您需要在包装面板中进行自定义绘画。因此,您不能只使用现有的 GUI 并旋转组件。 那么那个包装面板呢?我可以解决,但它不会解决面板上组件的痛苦?我之前尝试过,我也设法旋转它甚至组件,但是当组件更新时,他们重新绘制了它而不旋转。所以从我的角度来看,左上角应该是右下角“颠倒”。因为 JPanel 的旋转,我设置为内容窗格不知何故不会影响更新组件后的重绘。我不明白为什么。 @user1097772 我们在绕圈子。发布 SSCCE 来展示您正在尝试做的事情。坦率地说,你的要求对我来说没有任何意义。即使您旋转组件,它们也不会起作用,因为您将无法在文本字段中键入内容或使用鼠标与任何组件交互,因为这些事件将针对错误的点生成。

以上是关于发布覆盖java中组件的paint方法的主要内容,如果未能解决你的问题,请参考以下文章

覆盖paint()方法

如何正确覆盖 awt paint() 方法

Java Swing:在 JPanel 的组件下绘制?

java中paint()的具体用法是啥?

Java Paint 组件转换成位图

Java 的 JPanel 子类中重写父类的 paint 方法 会被自动调用,请问调用的条件或时机