How to expand the window by clicking a button?

Asked

Viewed 472 times

4

Is it possible to expand a window with more information when the user clicks a "Details" button? The behavior is similar to that of some error screens, which show the data of an error, as shown in the image below:

expanda ao clicar no botão por exemplo um JtexArea etc...

My window has a JButton which, when clicked, should expand the JDialog and display the contents of a JTextArea or ScrollPane.

  • You in case you want to mount a screen equal to the behavior of this...?

  • exact. A priori the screen will be smaller without showing these details, and then yes, when I click on Jbutton 'Details', it expands me and show me the details inside a Jtexarea and such... ?

  • I don’t have time to test the idea at the moment, so I won’t post an answer. But if you just hide/display the JTextArea at the click of the button, it should just be a matter of calling the method pack window.

  • Take a look at [tour]. You can accept an answer if it solved your problem. You can vote on every post on the site as well. Did any help you more? You need something to be improved?

2 answers

3

Apparently this message box appeared by capturing the exception made by Java itself. So there is nothing to do.

What you can do is you capture the exception in the proper location - it can be on main() - and treat it however you want. Then you show on a screen that you have control to do as you want programmatically, probably a JFrame.

You can choose the type of window you want and you can configure it as you think best.

It’s also possible to create a global manipulation, something like that:

public final class ExceptionHandler implements Thread.UncaughtExceptionHandler {
    @Override  public void uncaughtException(Thread thread, Throwable throwable) {
        JOptionPane.showMessageDialog(null, "Erro: " + throwable.toString(), 
            "Erro", JOptionPane.ERROR_MESSAGE);
    }
}

I put in the Github for future reference.

It’s just an example showing the overall capture of exceptions, of course this way using JOptionPane.showMessageDialog also there is little control.

  • This way I know how to do, however, I would like something more sophisticated for the user as shown in the image above. The idea I want is after clicking on a Jbutton the same expands me the Jdialog and show me what I want inside a Jtexarea/Scroolpane etc...

  • Then edit the question and enter the code of what you are doing and show your difficulty. You asked a generic question and I gave a generic answer. I can try to help.

2

This screen can be built entirely by hand, if you make sure to have it in your application, follow an example I developed, the code is with the proper observations:

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.JToggleButton;

/**
*
* @author diego.felipe
*/
public class DialogUnhandledException {

    // algumas IDE's podem reclamar de codificação de texto,
    // por causa destes simbolos, por isso deve-se manter
    // a codificação UTF-8 ou alterar os simbolos
    private static final String BUTTON_ARROW_NORTH = "▲";
    private static final String BUTTON_ARROW_SOUTH = "▼";
    private static final String MESSAGE_DEFAULT = "An unhandled exception has occurred in your application. "
            + "Click on Details for more information or click Quit to close the application immediately.";

    private DialogUnhandledException() {

    }

    public static void showException(String shortError, String strStackTrace) {

        // - fixedWith é um tamanho fixo para o frame não ficar redimensionando
        // ao abrir o JTextPane contendo a stacktrace.
        // - minHeight é o tamanho minimo do frame, quando o JTextPane da
        // StackTrace não estiver visível.
        // - maxHeight é a altura máxima do frame, comportando o JTextPane da
        // stracktrace aberto.
        int fixedWidth = 450;
        int minHeight = 135;
        int maxHeight = 300;

        JFrame frame = new JFrame();
        frame.getContentPane().setLayout(new BorderLayout());
        // obrigatório, para que o BorderLayout não redimensione automaticamente
        frame.setPreferredSize(new Dimension(fixedWidth, minHeight));
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        // painel principal que comportará os paineis de botoes
        // e da mensagem padrao
        JPanel principalPane = new JPanel();
        principalPane.setLayout(new BoxLayout(principalPane, BoxLayout.Y_AXIS));

        // painel onde será comportado o JTextPane com a mensagem
        // padrão mais a mensagem de erro sem o stacktrace
        JPanel messageDefaultPane = new JPanel(new BorderLayout(0, 5));
        messageDefaultPane.setBorder(BorderFactory.createEmptyBorder(3, 3, 0, 0));
        // componente onde será exibida a mensagem de erro padrao
        JTextPane tp_messageDefault = new JTextPane();
        tp_messageDefault.setBackground(frame.getBackground());
        tp_messageDefault.setEditable(false);
        tp_messageDefault.setText(MESSAGE_DEFAULT + "\n\n" + shortError);

        messageDefaultPane.add(tp_messageDefault, BorderLayout.CENTER);

        // scrollPane comportará o JTextPane que exibirá o stacktrace quando o
        // botao for clicado
        JScrollPane scrollPane = new JScrollPane();
        JTextPane tp_stackTrace = new JTextPane();
        tp_stackTrace.setBackground(frame.getBackground());
        tp_stackTrace.setEditable(false);

        // painel contendo os botoes Detais, Quit e Continue
        JPanel buttonPane = new JPanel();
        buttonPane.setLayout(new BoxLayout(buttonPane, BoxLayout.LINE_AXIS));
        buttonPane.setBorder(BorderFactory.createEmptyBorder(5, 0, 5, 10));

        // Como o estado do botão Details servirá para exibir ou ocultar
        // o JToggleButton faz mais sentido aqui
        JToggleButton btn_showDetails = new JToggleButton("Details " + BUTTON_ARROW_SOUTH);
        btn_showDetails.addItemListener(new ItemListener() {

            @Override
            public void itemStateChanged(ItemEvent e) {
                // quando o status do botao for "selecionado", a stacktrace será
                // atribuida no JTextPane, o frame terá sua altura alterada
                // para maxHeight e a posição da barra de scroll
                // ficará no topo do erro
                if (e.getStateChange() == ItemEvent.SELECTED) {
                    tp_stackTrace.setText(strStackTrace);
                    frame.setPreferredSize(new Dimension(fixedWidth, maxHeight));
                    tp_stackTrace.setCaretPosition(0);
                    frame.pack();
                    btn_showDetails.setText("Detalhes " + BUTTON_ARROW_NORTH);
                    // quando o status anterior do botao for desfeito, remove a
                    // stacktrace do componente de texto e redefine
                    // a altura minima para o frame
                } else if (e.getStateChange() == ItemEvent.DESELECTED) {
                    tp_stackTrace.setText(null);
                    frame.setPreferredSize(new Dimension(fixedWidth, minHeight));
                    frame.pack();
                    btn_showDetails.setText("Detalhes " + BUTTON_ARROW_SOUTH);
                }
            }
        });

        // funcionalidades não implementadas
        JButton btn_continue = new JButton("Continue");
        JButton btn_quit = new JButton("Quit");

        buttonPane.add(btn_showDetails);
        buttonPane.add(Box.createHorizontalGlue());
        buttonPane.add(btn_continue);
        buttonPane.add(Box.createRigidArea(new Dimension(10, 0)));
        buttonPane.add(btn_quit);

        scrollPane.setViewportView(tp_stackTrace);

        principalPane.add(messageDefaultPane);
        principalPane.add(buttonPane);

        frame.add(principalPane, BorderLayout.NORTH);
        frame.add(scrollPane, BorderLayout.CENTER);
        frame.pack();
        frame.setLocationRelativeTo(null);

        frame.setVisible(true);

    }

}

Its use is very simple, and following the @Maniero response, it can be used in conjunction with the class suggested in his reply, but for this, it is necessary to convert the error messages and the stackTrace for string:

import java.io.PrintWriter;
import java.io.StringWriter;

public final class ExceptionHandler implements Thread.UncaughtExceptionHandler {

    @Override
    public void uncaughtException(Thread thread, Throwable throwable) {

        StringWriter strStackTrace = new StringWriter();
        throwable.printStackTrace(new PrintWriter(strStackTrace));
        DialogUnhandledException.showException(throwable.toString(), strStackTrace.toString());
    }

}

To work, simply set the class as the default handler of exceptions not captured. The line below should be the first of the application:

public class Programa{

    public static void main(String[] args) {
        // registra nossa classe como manipulador padrao de 
        // exceções não capturadas   
        Thread.setDefaultUncaughtExceptionHandler(new ExceptionHandler());

            String a = null;
            System.out.println(a.equals(""));
            System.out.println(Integer.parseInt(a));
    }
}

A less drastic solution (also suggested by @Maniero in the other answer), is to put on main, surrounding the stretch that starts its application by a block try-catch:

public class Programa{

    public static void main(String[] args) {

        try {
            // define o look And Feel de acordo com o tema do SO em execução
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());

            String a = null;
            System.out.println(a.equals(""));
            System.out.println(Integer.parseInt(a));
        } catch (Exception e) {
            StringWriter strStackTrace = new StringWriter();
            e.printStackTrace(new PrintWriter(strStackTrace));
            SwingUtilities.invokeLater(() -> DialogUnhandledException.
                    showException(e.getClass() + " " + e.getMessage(),strStackTrace.toString()));
        }
    }
}

The result for both forms would be similar to the image below:

Mostrando a execução

Remembering that to look like this, it is necessary that it is running on Windows, if the Swing application runs on Linux or OSX, the appearance will be according to the running operating system theme.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.