亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

動畫定時paintComponent頂部的JButton

動畫定時paintComponent頂部的JButton

牛魔王的故事 2021-08-25 10:23:41
我有一個 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);                }            }            }        }    };  
查看完整描述

3 回答

?
Cats萌萌

TA貢獻1805條經驗 獲得超9個贊

如果您仔細觀察,當您將鼠標懸停在它們應該出現的位置時,您會看到按鈕彈出。

這意味著您有 ZOorder 問題。ZOrder 是組件在 z 軸上彼此堆疊時繪制的順序。

Swing 以組件添加到面板的相反順序繪制組件,因此最后添加的組件首先被繪制。所以聽起來你有多個面板堆疊在一起,你添加的最后一個面板包含按鈕,但它首先被繪制,所以所有其他面板都在它上面繪制。

當鼠標移到按鈕上時,按鈕需要重新繪制自身以顯示按鈕的滾動效果,因此按鈕暫時被繪制在頂部,直到重新建立正確的 ZOrder 時父面板的下一次重新繪制。

我對您的程序結構了解得不夠多,但我會質疑為什么您將一堆面板堆疊在一起。您只需要一個帶有自定義繪畫的面板,然后將按鈕放置在該面板上。


查看完整回答
反對 回復 2021-08-25
?
Helenr

TA貢獻1780條經驗 獲得超4個贊

您的主要問題就在這里...


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();   

你的第二個錯誤是...


new Timer().scheduleAtFixedRate(new TimerTask() {

    @Override

    public void run() {

        update();

    }

}, 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));。這根本沒有意義。


該文檔的狀態


 公共無效旋轉(雙θ,

                   雙錨x,

                   雙錨) 

將此變換與圍繞錨點旋轉坐標的變換連接起來。這個操作相當于平移坐標,使錨點在原點(S1),然后繞新原點(S2)旋轉,最后平移,使中間原點恢復到原錨點的坐標(S3)。此操作等效于以下調用序列:


 translate(anchorx, anchory);      // S3: final translation

 rotate(theta);                    // S2: rotate around anchor

 translate(-anchorx, -anchory);    // S1: translate anchor to origin   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#create

http://img1.sycdn.imooc.com//6125a9ec0001576702360235.jpg

import 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 {


    public static void main(String[] args) {

        new Test();

    }


    public Test() {

        EventQueue.invokeLater(new Runnable() {

            @Override

            public void run() {

                try {

                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());

                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {

                    ex.printStackTrace();

                }


                JFrame frame = new JFrame("Testing");

                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

                frame.add(new TestPane());

                frame.pack();

                frame.setLocationRelativeTo(null);

                frame.setVisible(true);

            }

        });

    }


    public class TestPane extends JPanel {


        private double angle;


        public TestPane() {

            setLayout(new GridBagLayout());

            for (int index = 0; index < 5; index++) {

                add(new JButton("Here"));

            }


            Timer timer = new Timer(5, new ActionListener() {

                @Override

                public void actionPerformed(ActionEvent e) {

                    angle += 0.01;

                    repaint();

                }

            });

            timer.start();

        }


        @Override

        public Dimension getPreferredSize() {

            return new Dimension(400, 400);

        }


        protected void paintComponent(Graphics g) {

            super.paintComponent(g);

            Graphics2D g2d = (Graphics2D) g.create();

            //Graphics2D g2d = (Graphics2D) g;

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


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

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

            g2d.drawRect(-50, -50, 100, 100);

            g2d.setColor(Color.RED);

            g2d.rotate(angle, 0, 0);

            g2d.drawRect(-100, -100, 200, 200);

            g2d.dispose();

        }


    }


}

不使用 Graphics#create

http://img1.sycdn.imooc.com//6125aa06000110ce04620473.jpg

哦,哦,我的按鈕在哪里 - 根據您對Graphics上下文所做的更改,可能圍繞容器的中心點旋轉了 90 度,所以現在它們可能不在屏幕上



查看完整回答
反對 回復 2021-08-25
?
臨摹微笑

TA貢獻1982條經驗 獲得超2個贊

我已經轉移到 JLayeredPane 以獲得我正在尋找的效果。我可以點擊頂層并拖動底層。

http://img1.sycdn.imooc.com//6125aa370001ab8119171083.jpg

  LayerUI backgroundUI = new WallpaperLayerUI();

    jlayer = new JLayer<JPanel>(panel, backgroundUI);


    LayerUI controlsUI = new LayerUI();

    JPanel controlPanel = new JPanel();

    MigLayout layout = new MigLayout(

            "debug, insets 10, gap 10, wrap", // Layout Constraints

            "[fill,grow][fill,grow][fill,grow]", // Column constraints with default align

            "[fill,grow][fill,grow][fill,grow]");

    controlPanel.setLayout(layout);

    controlPanel.add(new JButton("here"));

    controlPanel.add(new JButton("here"));

    controlPanel.add(new JButton("here"));

    controlPanel.add(new JButton("here"));

    controlPanel.add(new JButton("here"));

    controlPanel.add(new JButton("here"));

    controlPanel.add(new JButton("here"));

    controlPanel.add(new JButton("here"));

    controlPanel.add(new JButton("here"));


    jlayer2 = new JLayer<JPanel>(controlPanel, controlsUI);


    panel.addMouseListener(this);

    panel.addMouseMotionListener(this);

    panel.addMouseWheelListener(this);


    finalPanel = new JLayeredPane();

    finalPanel.setPreferredSize(new Dimension(300, 310));

    //finalPanel.setLayout(null);

    jlayer.setBounds(0, 0, (808-40)/3, (608-40)/3);

    jlayer2.setBounds(0, 0, (808-80)/3, (608-80)/3);

    controlPanel.setBackground(new Color(0,0,0,0));

    finalPanel.add(jlayer, new Integer(0));

    finalPanel.add(jlayer2 ,new Integer(1));


查看完整回答
反對 回復 2021-08-25
  • 3 回答
  • 0 關注
  • 216 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號