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

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

為什么透明的 JButton 在添加透明度時顯示框架的圖像?

為什么透明的 JButton 在添加透明度時顯示框架的圖像?

LEATH 2023-02-23 10:45:47
我正在為 Java 應用程序開發一個 GUI,我想要一個背景圖像。問題是我有一種充滿按鈕的“抽屜”,當被選中時,按鈕會以紅色突出顯示。我正在使用方法 buttonName.setBackground(new Color(255, 102, 102, 200)); 同時設置高亮按鈕和透明度。問題是,盡管該方法有效并使按鈕透明,但透明度會顯示按鈕后面框架的隨機部分,這些是標題,另一個按鈕,按鈕所在的 JScrollPane 的滾動條等。按鈕仍然顯示,并且按鈕有效,但背景顯示來自其他按鈕或框架部分的文本。此外,我意識到,如果我單擊一個按鈕并將鼠標多次移到所選按鈕上,透明度就會開始累積,直至變成純色。如果有人知道如何制作干凈透明的按鈕,我將不勝感激。我在這里留下了源代碼和我正在使用的測試圖像。 https://drive.google.com/file/d/1l8R52WTDyP93L0UhTNd3oorD7Qhv-TcP/view?usp=sharing在這張圖片中,您可以看到我遇到的 3 種錯誤,在第一種錯誤中,您可以看到背景中有另一個按鈕,滾動條顯示在按鈕的左側。在第二個中,它是導航面板的標題。在第三個中,我將鼠標多次移到選定的按鈕上,它變成了純色而不是透明的。編輯:如果我將它應用到導航面板,我決定檢查錯誤是否仍然存在,因為當應用程序完成時它也必須是透明的。于是我在上面代碼的第82行和83行添加了如下幾行代碼:        panelNav.setBackground(new Color(0, 0, 0, 200));         panelNav.setOpaque(true);在另一張圖片中,我將透明度應用于整個導航面板,這是一個 JLabel。在第一個圖像中顯示了顯示框架時出現的內容,甚至還有部分框架顯示在導航面板下方。在第二個中顯示了當我使用一次滾動條時會發生什么。編輯 2:我將所有用作 JPanel 的 JLabel 替換為實際的 JPanel??杀氖?,錯誤仍然存在。我在主 JPanel 中添加了一個額外的按鈕,我這樣做是因為我認為錯誤起源于向 JScrollPane 添加按鈕。但問題似乎直接在于我如何實現方法 buttonName.setBackground()。這是新版本的代碼: https://drive.google.com/file/d/1PuHMkEYNbBoafqs5XiyUaeCkIyXfnHFJ/view ?usp=sharing
查看完整描述

1 回答

?
汪汪一只貓

TA貢獻1898條經驗 獲得超8個贊

在 99% 的案例中,您在示例應用程序中看到的任何問題都是由于不透明和/或非不透明組件的不正確混合而發生的。


正如我從代碼中看到的那樣 - 您正在使用setOpaque(...)來更改各種組件的不透明度,但它非?;靵y。很快,opaque屬性的作用 - 它會影響 Swing 在需要對特定 UI 元素(面板/標簽/按鈕/等)進行視覺更新時重新繪制該元素的方式。


例如,當您用鼠標懸停按鈕時 - 如果它具有不同的懸停狀態,則可能需要重新繪制它,無論它只是一個圖標還是稍微/完全不同的樣式。這就是不透明度發揮作用的地方——opaque=true組件永遠不會在它們自己的“下方”傳遞重繪調用(用其他/適當的術語來說——傳遞給它們的父組件)。這意味著如果您在面板上有一個不透明的按鈕,并且當它變為“懸?!睜顟B時必須重新繪制它 - 該按鈕將是唯一要重新繪制的組件,因為沒有理由重新繪制它下面的任何東西,因為它是不透明,你實際上不應該能夠看透它,所以圖形應該用不透明的顏色填充該按鈕邊界內的所有像素。


理論上。在實踐中,如果您將按鈕設置為不透明狀態,但保持其圖形內容透明或半透明(這顯然是一個錯誤,但 Swing 永遠不會告訴您)——您最終會看到各種視覺偽像,例如你在你的應用程序中看到。發生這種情況是因為Graphics2D實現經常在 (0,0) 坐標執行不同的繪制操作以優化它們的速度——知道這一點并不重要,但這部分是為什么你可能會看到其他組件“部分”混合在你的組件邊界時是透明的。它比那更復雜一點,但它不應該真正重要,因為它只是一個內部 Swing 優化。


類似的視覺問題也可能是由同一布局上的混合opaque=true和組件引起的。opaque=false您的問題很可能也是如此。我確實很快嘗試將您的演示中的所有內容都設置為opaque=false并且它確實解決了問題,但這并不是解決問題的正確方法,特別是如果您想讓某些組件不透明。這只是意味著問題在于在單個容器中將具有不同不透明度類型的組件相互混合的方式。


我的個人建議 - 永遠不要在一個布局中混合不透明和非不透明組件,即使它們有可能重疊(意味著它們的邊界將在布局內相交)。甚至更好——永遠不要在單個容器中將組件重疊在一起。使用具有適當非空布局的多個嵌套容器,這也將在以后幫助您輕松修改 UI。


我可以給你一個簡單的例子來說明為什么它不好:


/**

 * @author Mikle Garin

 */

public class OpacityGlitch

{

    public static void main ( String[] args )

    {

        SwingUtilities.invokeLater ( () -> {

            final JFrame frame = new JFrame ( "Opacity glitch sample" );


            // Opaque by default

            final JPanel panel = new JPanel ( null );


            // Opaque by default, but might vary with L&F

            final JButton button1 = new JButton ( "1111111" );

            panel.add ( button1 );


            // Non-opaque to demonstrate the problem

            final JButton button2 = new JButton ( "2222222" );

            panel.add ( button2 );


            // Intersecting buttons

            button1.setBounds ( 100, 100, 150, 30 );

            button2.setBounds ( 130, 115, 150, 30 );


            frame.getContentPane ().add ( panel );


            frame.setDefaultCloseOperation ( JFrame.EXIT_ON_CLOSE );

            frame.setSize ( 500, 500 );

            frame.setLocationRelativeTo ( null );

            frame.setVisible ( true );

        } );

    }

}

理論上你應該得到的button1總是在最上面(因為它被更早地添加并且最后被涂在容器上),但在實踐中 - 如果你嘗試懸停其中一個按鈕,那么哪個按鈕是完全可見的并且在另一個按鈕之上將會改變按鈕。發生這種情況是因為兩個按鈕都是不透明的,并且重繪調用不會通過按鈕組件到達它們的容器以及與它們進一步相交的任何內容。button2要解決這種特殊情況,使其成為非不透明就足夠了,因為它應該始終保持在 下方button1,并且如果它是非不透明的,它將安全地將重繪調用至少傳遞給它的容器:


button2.setOpaque ( false );

盡管我個人建議在這種情況下使所有涉及的組件不透明,以避免在將來可能更改組件順序或由于任何用戶交互而發生其他可能的問題——例如,應用程序中的滾動條就是最好的例子。容器不必是非不透明的,因為它會正確地在放置在其中的組件之間傳遞重繪調用,并且也會正確地重繪自身。


一旦將我上面示例中的按鈕更改為非不透明,由于為它們正確處理了重繪,問題就會消失。


對于 Swing 的初學者來說,這可能是一個復雜的話題,但我強烈建議您充分理解為什么會發生這種情況以及如何發生這種情況,否則一旦您的應用程序變大,它將成為您未來的一個大問題。


查看完整回答
反對 回復 2023-02-23
  • 1 回答
  • 0 關注
  • 128 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

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

幫助反饋 APP下載

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

公眾號

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