动画定时paintComponent顶部的JButton

我有一个 BVH 播放器,它有 9 个视图,可以在计时器上为它们设置动画,我试图将控件放在每个面板的顶部以单独控制变换操作。


按钮呈现在我的paintComponent 后面,但有时可以单击。我还有一个 MouseListener 来调整骨架的变换,有时它可以工作。我可以发布听众,但我认为这并不重要。



我尝试了 graphics.dispose 和 graphics2d.dispose 的各种组合,并尝试以奇怪的结果改变 super.paintComponent(g) 的位置,但没有任何好处。


下面是显示问题的视频。如果您仔细观察,当您将鼠标悬停在它们应该出现的位置时,您会看到按钮弹出。您还会看到,当我 g.dispose() 时,它在两个地方的按钮变得陌生,但只在一个地方单击(这不是它们最明显的地方)。 https://youtu.be/CyFpUlbFI1U


这是我的源代码:


public SkeletonPlayer(int camera, double scale, int rotLeftRight, int rotUpDown, double translateLeftRight, double translateUpDown) {

    this.camera = camera;

    this.scale = scale;

    this.rotLeftRight = rotLeftRight;

    this.rotUpDown = rotUpDown;

    this.translateLeftRight = translateLeftRight;

    this.translateUpDown = translateUpDown;

    panel = new JPanel() {

        @Override

        protected void paintComponent(Graphics g) {

            super.paintComponent(g);

            Graphics2D g2d = (Graphics2D) g;

            g2d.translate(getWidth() / 2, getHeight() / 2);


            AffineTransform at = AffineTransform.getTranslateInstance(0, 0);

            at.rotate(Math.toRadians(90), Math.toRadians(90), Math.toRadians(90));


            for (int n = 0; n < MainFrame.skeleton[camera].getNodes().size(); n++) {

                Node node = MainFrame.skeleton[camera].getNodes().get(n);

                int x1 = (int) (scale * node.getPosition().getX());

                int y1 = (int) (-scale * node.getPosition().getY());

                g2d.setColor(Color.RED);

                g2d.fillOval((int) (x1 - 2), (int) (y1 - 2), 4, 4);


                g2d.setColor(Color.BLACK);

                //g2d.drawString(node.getName(), x1 + 10, y1);


                for (Node child : node.getChildrens()) {

                    int x2 = (int) (scale * child.getPosition().getX());

                    int y2 = (int) (-scale * child.getPosition().getY());

                    g2d.drawLine(x1, y1, x2, y2);

                }

            }

            }

        }

    };

  


牛魔王的故事
浏览 184回答 3
3回答

Cats萌萌

如果您仔细观察,当您将鼠标悬停在它们应该出现的位置时,您会看到按钮弹出。这意味着您有 ZOorder 问题。ZOrder 是组件在 z 轴上彼此堆叠时绘制的顺序。Swing 以组件添加到面板的相反顺序绘制组件,因此最后添加的组件首先被绘制。所以听起来你有多个面板堆叠在一起,你添加的最后一个面板包含按钮,但它首先被绘制,所以所有其他面板都在它上面绘制。当鼠标移到按钮上时,按钮需要重新绘制自身以显示按钮的滚动效果,因此按钮暂时被绘制在顶部,直到重新建立正确的 ZOrder 时父面板的下一次重新绘制。我对您的程序结构了解得不够多,但我会质疑为什么您将一堆面板堆叠在一起。您只需要一个带有自定义绘画的面板,然后将按钮放置在该面板上。

Helenr

您的主要问题就在这里...Graphics2D g2d = (Graphics2D) g;g2d.translate(getWidth() / 2, getHeight() / 2);AffineTransform at = AffineTransform.getTranslateInstance(0, 0);Graphics传递给组件的上下文是共享资源,它会传递给在绘制周期中绘制的所有组件,这意味着当您更改原点和旋转等内容时,它会影响在它之后绘制的所有组件。相反,您应该Graphics在应用更改之前创建状态的副本,这会保持原始状态不变Graphics2D g2d = (Graphics2D) g.create();g2d.translate(getWidth() / 2, getHeight() / 2);AffineTransform at = AffineTransform.getTranslateInstance(0, 0);//...g2d.dispose();&nbsp; &nbsp;你的第二个错误是...new Timer().scheduleAtFixedRate(new TimerTask() {&nbsp; &nbsp; @Override&nbsp; &nbsp; public void run() {&nbsp; &nbsp; &nbsp; &nbsp; update();&nbsp; &nbsp; }}, 0, (long) Math.round(motion.getFrameTime() * 1000));Swing 不是线程安全的,更新 UI 或 UI 所依赖的状态可能会产生意外且难以诊断的结果。在这种情况下,您有两种选择,根据您的需要使用 SwingTimer或 a SwingWorker。查看Swing中的并发以获取更多详细信息另一个问题是at.rotate(Math.toRadians(90), Math.toRadians(90), Math.toRadians(90));。这根本没有意义。该文档的状态&nbsp;公共无效旋转(双θ,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;双锚x,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;双锚)&nbsp;将此变换与围绕锚点旋转坐标的变换连接起来。这个操作相当于平移坐标,使锚点在原点(S1),然后绕新原点(S2)旋转,最后平移,使中间原点恢复到原锚点的坐标(S3)。此操作等效于以下调用序列:&nbsp;translate(anchorx, anchory);&nbsp; &nbsp; &nbsp; // S3: final translation&nbsp;rotate(theta);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // S2: rotate around anchor&nbsp;translate(-anchorx, -anchory);&nbsp; &nbsp; // S1: translate anchor to origin&nbsp; &nbsp;Rotating by a positive angle theta rotates points on the正 X 轴朝向正 Y 轴。另请注意上述处理 90 度旋转的讨论。参数:theta- 以弧度为单位anchorx的旋转角度anchory-旋转锚点的 X 坐标 - 旋转锚点的 Y 坐标这就是说,第二个和第三个参数实际上是旋转发生的点。在你的情况下at.rotate(Math.toRadians(90), 0, 0);可能是你真正想要的。使用 Graphics#createimport java.awt.Color;import java.awt.Dimension;import java.awt.EventQueue;import java.awt.Graphics;import java.awt.Graphics2D;import java.awt.GridBagLayout;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.awt.geom.AffineTransform;import javax.swing.JButton;import javax.swing.JFrame;import javax.swing.JPanel;import javax.swing.Timer;import javax.swing.UIManager;import javax.swing.UnsupportedLookAndFeelException;public class Test {&nbsp; &nbsp; public static void main(String[] args) {&nbsp; &nbsp; &nbsp; &nbsp; new Test();&nbsp; &nbsp; }&nbsp; &nbsp; public Test() {&nbsp; &nbsp; &nbsp; &nbsp; EventQueue.invokeLater(new Runnable() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @Override&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; public void run() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; try {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ex.printStackTrace();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; JFrame frame = new JFrame("Testing");&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; frame.add(new TestPane());&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; frame.pack();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; frame.setLocationRelativeTo(null);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; frame.setVisible(true);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; });&nbsp; &nbsp; }&nbsp; &nbsp; public class TestPane extends JPanel {&nbsp; &nbsp; &nbsp; &nbsp; private double angle;&nbsp; &nbsp; &nbsp; &nbsp; public TestPane() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; setLayout(new GridBagLayout());&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for (int index = 0; index < 5; index++) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; add(new JButton("Here"));&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Timer timer = new Timer(5, new ActionListener() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @Override&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; public void actionPerformed(ActionEvent e) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; angle += 0.01;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; repaint();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; });&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; timer.start();&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; @Override&nbsp; &nbsp; &nbsp; &nbsp; public Dimension getPreferredSize() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return new Dimension(400, 400);&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; protected void paintComponent(Graphics g) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; super.paintComponent(g);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Graphics2D g2d = (Graphics2D) g.create();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //Graphics2D g2d = (Graphics2D) g;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; g2d.translate(getWidth() / 2, getHeight() / 2);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AffineTransform at = AffineTransform.getTranslateInstance(0, 0);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; at.rotate(Math.toRadians(90), 0, 0);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; g2d.drawRect(-50, -50, 100, 100);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; g2d.setColor(Color.RED);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; g2d.rotate(angle, 0, 0);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; g2d.drawRect(-100, -100, 200, 200);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; g2d.dispose();&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}不使用&nbsp;Graphics#create哦,哦,我的按钮在哪里 - 根据您对Graphics上下文所做的更改,可能围绕容器的中心点旋转了 90 度,所以现在它们可能不在屏幕上

临摹微笑

我已经转移到 JLayeredPane 以获得我正在寻找的效果。我可以点击顶层并拖动底层。&nbsp; LayerUI backgroundUI = new WallpaperLayerUI();&nbsp; &nbsp; jlayer = new JLayer<JPanel>(panel, backgroundUI);&nbsp; &nbsp; LayerUI controlsUI = new LayerUI();&nbsp; &nbsp; JPanel controlPanel = new JPanel();&nbsp; &nbsp; MigLayout layout = new MigLayout(&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "debug, insets 10, gap 10, wrap", // Layout Constraints&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "[fill,grow][fill,grow][fill,grow]", // Column constraints with default align&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "[fill,grow][fill,grow][fill,grow]");&nbsp; &nbsp; controlPanel.setLayout(layout);&nbsp; &nbsp; controlPanel.add(new JButton("here"));&nbsp; &nbsp; controlPanel.add(new JButton("here"));&nbsp; &nbsp; controlPanel.add(new JButton("here"));&nbsp; &nbsp; controlPanel.add(new JButton("here"));&nbsp; &nbsp; controlPanel.add(new JButton("here"));&nbsp; &nbsp; controlPanel.add(new JButton("here"));&nbsp; &nbsp; controlPanel.add(new JButton("here"));&nbsp; &nbsp; controlPanel.add(new JButton("here"));&nbsp; &nbsp; controlPanel.add(new JButton("here"));&nbsp; &nbsp; jlayer2 = new JLayer<JPanel>(controlPanel, controlsUI);&nbsp; &nbsp; panel.addMouseListener(this);&nbsp; &nbsp; panel.addMouseMotionListener(this);&nbsp; &nbsp; panel.addMouseWheelListener(this);&nbsp; &nbsp; finalPanel = new JLayeredPane();&nbsp; &nbsp; finalPanel.setPreferredSize(new Dimension(300, 310));&nbsp; &nbsp; //finalPanel.setLayout(null);&nbsp; &nbsp; jlayer.setBounds(0, 0, (808-40)/3, (608-40)/3);&nbsp; &nbsp; jlayer2.setBounds(0, 0, (808-80)/3, (608-80)/3);&nbsp; &nbsp; controlPanel.setBackground(new Color(0,0,0,0));&nbsp; &nbsp; finalPanel.add(jlayer, new Integer(0));&nbsp; &nbsp; finalPanel.add(jlayer2 ,new Integer(1));
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java