1

I've got a probelm with my swing ui lately. Everything works fine,untill i trigger a tooltip from a JButton.After that moving the mouse over the rest of the ui is causing weird artifacts and glitching.

Bugged:

enter image description here

I can't show the whole code because its too much but here im initialising the button :

    GridBagConstraints bottompane_gbc = new GridBagConstraints();
    toggleTorConnectionButton = new JButton();      
    toggleTorConnectionButton.setToolTipText("Toggles Tor Connection.");
    toggleTorConnectionButton.setIcon(new ImageIcon(ResourceHandler.Menueicon3_1));
    toggleTorConnectionButton.setMinimumSize(new Dimension(removeFinishedDownloads.getMinimumSize().width, toggleTorConnectionButton.getIcon().getIconHeight()+5));

    toggleTorConnectionButton.addActionListener(); // unimportant
    bottompane_gbc.gridy = 1;
    bottompane_gbc.fill = GridBagConstraints.BOTH;
    bottompane_gbc.insets = new Insets(0,15,10,5);
    bottompane.add(ToggleTorConnectionButton,bottompane_gbc);


    this.add(bottompane,BorderLayout.PAGE_END);

If anybody needs more information to help me pls feel free to ask.Im kind of desperated. XD

EDIT: After some tinkering im guessing that the problem is related to swing and my use of it.Currently im using alot of Eventlisteners (is this bad?), that might slow down the awt thread ? Here is a brief extract from HPROF: http://www.pastebucket.com/96444

EDIT 2: I was able to recreate the error in a handy and simple example. When you move over the button,wait for the tooltip and then over the ui.You will see ghosting :(.

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;

public class Main_frame {

    public static void main(String[] args) {
        new Main_frame();
    }

    public Main_frame() {
        JFrame frame = new JFrame("LOL");
        frame.setFocusable(true);
        frame.setResizable(false);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.setSize(new Dimension(400, 500));
        frame.setLocationRelativeTo(null);

        Download_window download_window = new Download_window();
        JTabbedPane tabbedPane = new JTabbedPane();
        tabbedPane.addTab("Download", null, download_window, "Main Download Window.");

        for (int i = 0; i < 5; i++) {
            JPanel pane = new JPanel();
            Dimension dim = new Dimension(370, 60);
            pane.setPreferredSize(dim);
            pane.setMaximumSize(dim);
            pane.setBackground(Color.blue);
            pane.setMinimumSize(dim);
            download_window.jobpanel.add(pane);
        }
        download_window.jobpanel.repaint();
        download_window.jobpanel.revalidate();

        frame.add(tabbedPane);
        frame.setVisible(true);
    }

    public class Download_window extends JPanel {

        JPanel jobpanel;

        public Download_window() {
            this.setLayout(new BorderLayout());

            jobpanel = new JPanel();
            jobpanel.setLayout(new BoxLayout(jobpanel, BoxLayout.Y_AXIS));

            JPanel bottompane = new JPanel();
            bottompane.setPreferredSize(new Dimension(385, 40));

            JButton toggleTorConnectionButton = new JButton();
            toggleTorConnectionButton.setPreferredSize(new Dimension(100, 50));
            toggleTorConnectionButton.setToolTipText("Toggles Tor Connection.");

            bottompane.add(toggleTorConnectionButton);

            this.add(bottompane, BorderLayout.PAGE_END);
            JScrollPane jobScrollPane = new JScrollPane(jobpanel);
            jobScrollPane.getVerticalScrollBar().setUnitIncrement(16);
            this.add(jobScrollPane, BorderLayout.CENTER);

        }
    }
}

Edit 3: Concerning trashgods ideas, I used the EventDispatchThread, I modified the setter to override the getter for size and i crossed out incompatibility by using trashgods code and it was working fine.... So where is the actual difference?

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;

public class Main_frame {

public static void main(String[] args) {
     EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                new Main_frame();
            }
     });
}

public Main_frame() {
    JFrame frame = new JFrame("LOL");
    frame.setResizable(false);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(new Dimension(400, 500));

    Download_window download_window = new Download_window();
    JTabbedPane tabbedPane = new JTabbedPane();
    tabbedPane.addTab("Download", null, download_window, "Main Download Window.");
    frame.add(tabbedPane);

    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
}

public class Download_window extends JPanel {

    JPanel jobpanel;

    public Download_window() {
        this.setLayout(new BorderLayout());

        jobpanel = new JPanel();
        jobpanel.setLayout(new BoxLayout(jobpanel, BoxLayout.Y_AXIS));
        for (int i = 0; i < 5; i++) {
            JPanel pane = new JPanel(){
                @Override
                public Dimension getPreferredSize() {
                    return new Dimension(370, 60);
                }
                @Override
                public Dimension getMaximumSize() {
                    return new Dimension(370, 60);
                }
                @Override
                public Dimension getMinimumSize() {
                    return new Dimension(370, 60);
                }
            };
            pane.setBackground(Color.blue);
            jobpanel.add(pane);
        }

        JPanel bottompane = new JPanel(){
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(385, 40);
            }
        };

        JButton toggleTorConnectionButton = new JButton("Button"){
             @Override
             public Dimension getPreferredSize() {
                 return new Dimension(100, 30);
             }
        };
        toggleTorConnectionButton.setToolTipText("Toggles Tor Connection.");
        bottompane.add(toggleTorConnectionButton);
        this.add(bottompane, BorderLayout.PAGE_END);


        JScrollPane jobScrollPane = new JScrollPane(jobpanel);
        jobScrollPane.getVerticalScrollBar().setUnitIncrement(16);
        this.add(jobScrollPane, BorderLayout.CENTER);

    }
}
}

Could anyone please verify that strange behavior himself? You just need to copy&paste the code from above in Edit3.

jan b
  • 29
  • 7
  • 1
    Variable names should NOT start with an upper case character. Some variable are correct. Other are not. Follow Java conventions and be consistent!!! Post a proper [SSCCE](http://sscce.org/) that demonstrates the problem. – camickr Dec 16 '15 at 15:36
  • 3
    1. Don't post htm links but image links as the latter is safer for us. 2. Are you overriding `paint` or `paintComponent` anywhere? If so you're likely not calling the super method. 3. @camickr speaks the truth. Create and post your [mcve] so we can reproduce your problem and help you solve it. – Hovercraft Full Of Eels Dec 16 '15 at 15:48
  • Well i technicially dont know how to create such an example, because im guessing that the problem is releated to my program as one. – jan b Dec 16 '15 at 15:51
  • 1
    Jan: now's a good time to learn. Start cutting away at your program piece by piece until you isolate the problem. – Hovercraft Full Of Eels Dec 16 '15 at 15:57
  • 1
    `Currently im using alot of Eventlisteners` - so get rid of the event listeners and see if you still have a problem. `im guessing that the problem is related to swing and my use of it` yes, the problem is how you are using Swing, but we can't tell what you are doing based on 10 lines of code. Or another approach when learning a new concept is to create a simple JFrame with a single button and see if you have a problem. Then add in some extra logic. Repeat until you isolate the problem. The point is it that debugging is easier with a small amount of code. – camickr Dec 16 '15 at 15:58
  • Check for [driver problems](http://stackoverflow.com/q/22737535/230513). – trashgod Dec 16 '15 at 17:35
  • “…no exceptions at all untill i trigger a tooltip from a JButton.” Include the full stack trace from one of those exceptions in your question. It probably will tell you (and us) what is going wrong, where, and why. – VGR Dec 16 '15 at 17:39
  • “…no exceptions at all untill i trigger a tooltip from a JButton.” that was my bad, sorry.Actually i wanted to say that there isn't an exception at all.I edited that passage. – jan b Dec 16 '15 at 18:13

1 Answers1

6

Your code exhibits none of the glitches shown above when run on my platform.

  • Verify that you have no painting problems e.g. neglecting super.paintComponent() as discussed here.

  • Verify that you have no driver incompatibilities, as discussed here.

  • Construct and modify all GUI objects on the event dispatch thread.

  • Don't use set[Preferred|Maximum|Minimum]Size() when you really mean to override get[Preferred|Maximum|Minimum]Size(), as discussed here. The example below overrides getPreferredSize() on the scroll pane, but you can implement Scrollable, as discussed here.

image

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;

/** @see https://stackoverflow.com/a/34319260/230513 */
public class MainFrame {

    private static final int H = 64;

    public static void main(String[] args) {
        EventQueue.invokeLater(() -> new MainFrame());
    }

    public MainFrame() {
        JFrame frame = new JFrame("LOL");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JTabbedPane tabbedPane = new JTabbedPane();
        JPanel panel = new JPanel(new GridLayout(0, 1, 5, 5));
        for (int i = 0; i < 8; i++) {
            panel.add(new DownloadPanel());
        }
        JScrollPane jsp = new JScrollPane(panel) {
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(6 * H, 4 * H);
            }
        };
        tabbedPane.addTab("Download", null, jsp, "Main Download Window.");
        tabbedPane.addTab("Options", null, null, "Options");
        frame.add(tabbedPane);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    private static class DownloadPanel extends JPanel {

        JPanel jobPanel = new JPanel();

        public DownloadPanel() {
            this.setLayout(new BorderLayout());
            this.setBackground(Color.lightGray);
            JProgressBar jpb = new JProgressBar();
            jpb.setIndeterminate(true);
            this.add(jpb);
            JPanel buttonPane = new JPanel();
            JButton toggleTorConnectionButton = new JButton("Button");
            toggleTorConnectionButton.setToolTipText("Toggles Tor Connection.");
            buttonPane.add(toggleTorConnectionButton);
            this.add(buttonPane, BorderLayout.WEST);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(4 * H, H);
        }
    }
}
Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • Thanks for your answer but it doesn't really shows me the obvious mistake in my code. I've tried your code, it is working. Now I've tried your recommendations in my code and it didn't changed anything :( – jan b Dec 16 '15 at 21:08
  • I *did not* know that `EventQueue.invokeLater(() -> new MainFrame());` is a substitute for the whole `new Runnable ... run()` thing. – user1803551 Dec 17 '15 at 06:52
  • 1
    @user1803551: See [*Lambda Expressions in GUI Applications*](https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html#lambda-expressions-in-gui-applications). – trashgod Dec 17 '15 at 10:02