0

I already found this topic but unfortunately it doesn't work. What I am trying to do: I am developing a little tool with help of Java Swing. For some functions in my tool I want to display a self designed tool tip in order to give some information.

Here is an example: Short text

This is my setting:

JDialog
+-jPanel (transparent container) 
| +-jPanel (dark background for my text pane)
|   +-jTextPane
+-jLabel (holds the arrow image)

If the user hover the little i he can see the info box. So far so good. I created a class for this info box and only set the text and make it visible ob mouse hover and make it unvisible on mouse exit.

This works like a charm. If I set another text (on another i to display another information I only use my public setText methode and again set it visible. See the next picture: Longer text, see auto height

The picture has the same width but another (auto) height. And now my problem: I want to be able to define another width (different to the default set one) to avoid to too high info box if the text is long. But if I do this my info box fails, see:

Long text with changed width, fail

This is my code (I removed the auto generated code by Netbeans):

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

public class MyToolTip extends javax.swing.JDialog {

    public MyToolTip(java.awt.Frame parent, boolean modal) {
        super(parent, modal);
        initComponents();
        makeMeTransparent();
    }

    public void setText (String text, Integer width) {
        String s;

        s  = "<html><body><p style=\"margin-top: 0; color: #ffffff; font-family:Tahoma; font-size:11px\">";
        s += text;
        s += "</p></body></html>";

        jTextPane_Tip.setText(s);

        if(width == 0) {
            width = 250;
        }

        setWidth(width);
        repaint();
        pack();
    }

    private void setWidth (Integer width) {        
        jTextPane_Tip.setSize(width, Integer.MAX_VALUE);
        jTextPane_Tip.setSize(width, jTextPane_Tip.getPreferredSize().height);
    }

    /* Netbeans auto generated code (hidden) */

    private void makeMeTransparent() {
        setBackground(new Color(0, 255, 0, 0));
        jPanel_Main.setBackground(new Color(0, 255, 0, 0));
        setContentPane(new MyContentPane());
        getContentPane().setBackground(Color.BLACK);
        setLayout(new BorderLayout());
        getContentPane().add(jPanel_Main);
    }
}

How to set width of a JTextPane and use auto height related to text?

Edit:

Here is now my minimal example:

File MyTT.java:

package mytt;

public class MyTT {

    public static void main(String[] args) {
        NewJFrame frame = new NewJFrame();
        frame.setVisible(true);
    }
}

File NewJFrame.java:

package mytt;

public class NewJFrame extends javax.swing.JFrame {

    private final MyToolTip tt;

    public NewJFrame() {
        initComponents();
        tt = new MyToolTip(this, false);
    }

    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() {

        jLabel1 = new javax.swing.JLabel();
        jLabel2 = new javax.swing.JLabel();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        jLabel1.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
        jLabel1.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        jLabel1.setText("Hover me for Tool-Tip (default width)");
        jLabel1.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseEntered(java.awt.event.MouseEvent evt) {
                jLabel1MouseEntered(evt);
            }
            public void mouseExited(java.awt.event.MouseEvent evt) {
                jLabel1MouseExited(evt);
            }
        });

        jLabel2.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
        jLabel2.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        jLabel2.setText("Hover me for Tool-Tip (user defined width)");
        jLabel2.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseEntered(java.awt.event.MouseEvent evt) {
                jLabel2MouseEntered(evt);
            }
            public void mouseExited(java.awt.event.MouseEvent evt) {
                jLabel2MouseExited(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jLabel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(jLabel2, javax.swing.GroupLayout.DEFAULT_SIZE, 280, Short.MAX_VALUE))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jLabel1)
                .addGap(108, 108, 108)
                .addComponent(jLabel2)
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        pack();
    }// </editor-fold>                        

    private void jLabel1MouseEntered(java.awt.event.MouseEvent evt) {                                     
        int x = jLabel1.getLocationOnScreen().x + jLabel1.getWidth() + 4;
        int y = jLabel1.getLocationOnScreen().y;   

        tt.setText("This is a simple example text. The width isn't changed and the height will be automatically set.",0);
        tt.setLocation(x,y);
        tt.setVisible(true);
    }                                    

    private void jLabel2MouseEntered(java.awt.event.MouseEvent evt) {                                     
        int x = jLabel2.getLocationOnScreen().x + jLabel1.getWidth() + 4;
        int y = jLabel2.getLocationOnScreen().y;   

        tt.setText("This is a simple example text. I set the width to a user defined value. This will crash the box somehow",400);
        tt.setLocation(x,y);
        tt.setVisible(true);
    }                                    

    private void jLabel1MouseExited(java.awt.event.MouseEvent evt) {                                    
        tt.setVisible(false);
    }                                   

    private void jLabel2MouseExited(java.awt.event.MouseEvent evt) {                                    
        tt.setVisible(false);
    }                                   

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /* Set the Nimbus look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(NewJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        //</editor-fold>

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(() -> {
            new NewJFrame().setVisible(true);
        });
    }

    // Variables declaration - do not modify                     
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    // End of variables declaration                   
}

File MyToolTip.java:

package mytt;

public class MyToolTip extends javax.swing.JDialog {

    public MyToolTip(java.awt.Frame parent, boolean modal) {
        super(parent, modal);
        initComponents();
    }

    public void setText (String text, Integer width) {     
        jTextPane_Tip.setText(text);

        // if the user doesn't defined a width, take the default width
        if(width == 0) width = 150;

        // resize the box
        setWidth(width);
    }

    private void setWidth (Integer width) {        
        jTextPane_Tip.setSize(width, Integer.MAX_VALUE);
        jTextPane_Tip.setSize(width, jTextPane_Tip.getPreferredSize().height);
        pack();
    }

    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() {

        jPanel_Main = new javax.swing.JPanel();
        jPanel_Background = new javax.swing.JPanel();
        jTextPane_Tip = new javax.swing.JTextPane();

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        setTitle("Variable Platzhalter");
        setFocusableWindowState(false);
        setUndecorated(true);
        addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent evt) {
                formKeyPressed(evt);
            }
        });

        jPanel_Background.setBackground(new java.awt.Color(29, 29, 29));

        jTextPane_Tip.setEditable(false);
        jTextPane_Tip.setBackground(new java.awt.Color(29, 29, 29));
        jTextPane_Tip.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
        jTextPane_Tip.setForeground(new java.awt.Color(255, 255, 255));
        jTextPane_Tip.setText("");

        javax.swing.GroupLayout jPanel_BackgroundLayout = new javax.swing.GroupLayout(jPanel_Background);
        jPanel_Background.setLayout(jPanel_BackgroundLayout);
        jPanel_BackgroundLayout.setHorizontalGroup(
            jPanel_BackgroundLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel_BackgroundLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jTextPane_Tip, javax.swing.GroupLayout.DEFAULT_SIZE, 150, Short.MAX_VALUE)
                .addContainerGap())
        );
        jPanel_BackgroundLayout.setVerticalGroup(
            jPanel_BackgroundLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel_BackgroundLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jTextPane_Tip)
                .addContainerGap())
        );

        javax.swing.GroupLayout jPanel_MainLayout = new javax.swing.GroupLayout(jPanel_Main);
        jPanel_Main.setLayout(jPanel_MainLayout);
        jPanel_MainLayout.setHorizontalGroup(
            jPanel_MainLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel_MainLayout.createSequentialGroup()
                .addGap(0, 0, 0)
                .addComponent(jPanel_Background, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
        jPanel_MainLayout.setVerticalGroup(
            jPanel_MainLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jPanel_Background, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );

        getContentPane().add(jPanel_Main, java.awt.BorderLayout.CENTER);

        pack();
        setLocationRelativeTo(null);
    }// </editor-fold>                        

    private void formKeyPressed(java.awt.event.KeyEvent evt) {                                
        this.dispose();
    }                               

    public static void main(String args[]) {
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(MyToolTip.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        /* Create and display the dialog */
        java.awt.EventQueue.invokeLater(() -> {
            MyToolTip dialog = new MyToolTip(new javax.swing.JFrame(), true);
            dialog.addWindowListener(new java.awt.event.WindowAdapter() {
                @Override
                public void windowClosing(java.awt.event.WindowEvent e) {
                    System.exit(0);
                }
            });
            dialog.setVisible(true);
        });
    }

    // Variables declaration - do not modify                     
    private javax.swing.JPanel jPanel_Background;
    private javax.swing.JPanel jPanel_Main;
    private javax.swing.JTextPane jTextPane_Tip;
    // End of variables declaration                   
}

Result of the minimal example: Okay, no user defined width Fail, with user defined width

Edit 2:

Okay second try: This I wrote an minimal example own my own (without auto generated code from Netbeans). I hope this is minimal enougth. And now the good news: The program acts exactly like I was expecting it (also from my real project).

MCVE.java: package mcve;

import java.awt.Dimension;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class MCVE {

    public static void main(String[] args) {

        MyToolTip tt = new MyToolTip(null,false);
        JFrame f = new JFrame();
        JLabel l1 = new JLabel("Please hover me (default size)");
        JLabel l2 = new JLabel("Please hover me (defined size)");
        JPanel p = new JPanel();

        l1.addMouseListener(new MouseAdapter() {

            @Override
            public void mouseEntered(MouseEvent evt) {
                int x = l1.getLocationOnScreen().x + l1.getWidth() + 4;
                int y = l1.getLocationOnScreen().y;   

                tt.setText("Lorem ipsum dolor sit amet, consetetur sadipscing elitr",200);
                tt.setLocation(x,y);
                tt.setVisible(true);
            }

            @Override
            public void mouseExited(MouseEvent evt) {
                tt.setVisible(false);
            }
        });

        l2.addMouseListener(new MouseAdapter() {

            @Override
            public void mouseEntered(MouseEvent evt) {
                int x = l2.getLocationOnScreen().x + l2.getWidth() + 4;
                int y = l2.getLocationOnScreen().y;   

                tt.setText("Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.",300);
                tt.setLocation(x,y);
                tt.setVisible(true);
            }

            @Override
            public void mouseExited(MouseEvent evt) {
                tt.setVisible(false);
            }
        });

        p.add(l1);
        p.add(l2);
        p.setPreferredSize(new Dimension(200,50));

        f.add(p);
        f.pack();
        f.setLocationRelativeTo(null);       
        f.setVisible(true);
    }
}

MyToolTip.java:

package mcve;

import java.awt.Dimension;
import javax.swing.JPanel;
import javax.swing.JTextPane;

public class MyToolTip extends javax.swing.JDialog { 
    private JPanel p;
    private JTextPane tp;

    public MyToolTip(java.awt.Frame parent, boolean modal) {
        super(parent, modal);
        initComp();
    }

    public void setText(String text, Integer width) {
        tp.setText(text);

        if(width > 0) {
            tp.setSize(width, Integer.MAX_VALUE);
            tp.setPreferredSize(new Dimension(width, tp.getPreferredSize().height));
        }

        pack();
    }

    private void initComp () {
        p = new JPanel();
        tp = new JTextPane();
        p.add(tp);
        add(p);
    }
}

The question is now: Why is it working in my second minimal example but not in my project :-(

PIC-Nico
  • 49
  • 9
  • *"I removed the auto generated code by Netbeans"* Well .. good, but .. For better help sooner, [edit] to add a [MCVE] or [Short, Self Contained, Correct Example](http://www.sscce.org/). – Andrew Thompson Feb 02 '19 at 12:49
  • Good point .. but my project is already very big. I will try to create a simple example. In the meantime here is my GitHub rep: https://github.com/PIC-Nico/InvoiceManagement – PIC-Nico Feb 02 '19 at 13:09
  • *"here is my GitHub rep"* I, and most people here, will not follow a link. Let alone follow a link to an entire GitHub repository. *"I will try to create a simple example."* Good. If you achieve that, let me know & I'll remove the close vote (which explicitly mentions 'no MCVE' as part of the reason). – Andrew Thompson Feb 02 '19 at 13:11
  • @AndrewThompson I added the minimal example. – PIC-Nico Feb 02 '19 at 13:40
  • > 250 lines of code (across 3 public classes) is not minimal. – Andrew Thompson Feb 02 '19 at 13:53
  • Sorry but I can not stop Netbeans from doing that auto generating code `¯\_(ツ)_/¯` – PIC-Nico Feb 02 '19 at 16:21
  • *"I can not stop Netbeans"* Then stop using it. Not our problem. – Andrew Thompson Feb 02 '19 at 16:22
  • Wow very polite ... I tried it with another example written without Netbeans. Now it is working but I have to figure out why it does not with my _real_ program. Anyway thank you. – PIC-Nico Feb 02 '19 at 20:11
  • *"Now it is working but I have to figure out why it does not with my real program."* So, progress then. (You're welcome.) – Andrew Thompson Feb 02 '19 at 23:50

1 Answers1

0

In setWidth(Integer) method in MyToolTip class, you are calling jTextPane_Tip.setSize() twice. When I removed the first call

jTextPane_Tip.setSize(width, Integer.MAX_VALUE);

it worked.

Prasad Karunagoda
  • 2,048
  • 2
  • 12
  • 16
  • No because setting a user defined width by the call `tt.setText("This is a simple example text. I set the width to a user defined value. This will crash the box somehow",400);` has (still) no effect. – PIC-Nico Feb 02 '19 at 16:36
  • @PIC-Nico, did you run your minimal program after removing above mentioned line? – Prasad Karunagoda Feb 02 '19 at 16:44
  • Yes I did. The height of the box will be auto set correct so that the complete text will be displayed **but** not with the width (400) I expected. – PIC-Nico Feb 02 '19 at 16:52