Acontece que quando eu uso essa classe junto com um jframe, por exemplo, toda a interface gráfica trava sendo necessário reiniciar a jvm.
Descobrir que isso acontece por conta do último while só que ao retirar-lo o método retorna false instantaneamente.
Então oq fazer nesse caso? Como posso esperar por uma ação seja feita antes de enviar a resposta sem que minha interface trave?
Como seu código está num evento, ele travou aquele segundo método ali. Portanto, o swing não repintará a tela.
Passando seu código para uma nova thread, o while do swing fica livre para realizar pintura enquanto seu cálculo está sendo realizado.
V
victorp_farias
Pois bem eu implementei Runnable e coloque o while(isvisible) dentro no método run() e chamei o meu thead start dentro do método valor, mas mesmo assim ele retorna false antes de ler qual botão/tecla pressionada.
ViniGodoy
Agora entendi o que você quer fazer…
Defina seu JDialog como modal. É so no construtor fazer:
Retire o setVisible(true) do construtor do seu JDialog. É uma péssima prática, pois vc está deixando uma janela não completamente construída visível. O método setVisible irá travar quando seu JDialog for modal, até que a janela feche.
Retire o static da sua variável resposta e do método valor();
Apague o while (ele não é necessário);
Você usa a JDialog assim:
MyJOptionPane dlg = new MyJOptionPane();
dlg.setVisible(true); //Vai travar até a janela fechar
if (dlg.valor()) {
System.out.println("Usuário pressionou sim");
else
System.out.println("Usuário pressionou não");
V
victorp_farias
Muito obrigado, funcionou perfeitamente.
Não conhecia esse metodo setModal().
De qualquer formar muito obrigado, tópico resolvido.
ViniGodoy
Tem vários problemas no seu código. Você cria toda uma classe de JDialog, mas no final acaba inserindo nele um JOptionPane com a janela.
Isso não faz o menor sentido.
O ideal é você realmente criar toda a dialog.
Veja um exemplo:
importjava.awt.BorderLayout;importjava.awt.FlowLayout;importjava.awt.event.ActionEvent;importjavax.swing.AbstractAction;importjavax.swing.Action;importjavax.swing.ActionMap;importjavax.swing.InputMap;importjavax.swing.JButton;importjavax.swing.JComponent;importjavax.swing.JDialog;importjavax.swing.JLabel;importjavax.swing.JPanel;importjavax.swing.KeyStroke;importjavax.swing.SwingConstants;publicclassMyJOptionPaneextendsJDialog{privateActionCloseactionSim=newActionClose("Sim - S",true);privateActionCloseactionNao=newActionClose("Não - N",false);privatebooleanresposta=false;privateMyJOptionPane(){StringkeySim="actionKeySim";StringkeyNao="actionKeyNao";InputMapinputMap=this.getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);inputMap.put(KeyStroke.getKeyStroke("S"),keySim);inputMap.put(KeyStroke.getKeyStroke("N"),keyNao);ActionMapactionMap=this.getRootPane().getActionMap();actionMap.put(keySim,actionSim);actionMap.put(keyNao,actionNao);JLabelmsg=newJLabel("Mensagem");msg.setHorizontalAlignment(SwingConstants.CENTER);add(msg,BorderLayout.CENTER);JPanelpnlButtons=newJPanel(newFlowLayout());pnlButtons.add(newJButton(actionSim));pnlButtons.add(newJButton(actionNao));add(pnlButtons,BorderLayout.SOUTH);setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);pack();setModal(true);setResizable(false);}/** * Lembre-se que a action também é um objeto. Você pode receber parâmetros e guarda-los em atributos. * O lugar certo de colocar o texto de botões, hints, teclas de aceleração é também na Action. Assim isso é * reaproveitado caso vc defina a action em vários locais. */privateclassActionCloseextendsAbstractAction{privatebooleanvalor;publicActionClose(Stringtexto,booleanvalor){this.valor=valor;putValue(Action.NAME,texto);}@OverridepublicvoidactionPerformed(ActionEvente){resposta=valor;dispose();}}/** * Esse método, além de dar um uso mais natural ao JDialog, garante que * a resposta sempre será false antes do setVisible ser chamado. Assim fica * fácil de usar o JDialog 2 vezes. * * @return True se sim foi clicado. */publicbooleanshowConfirm(){resposta=false;setVisible(true);returnresposta;}publicstaticvoidmain(String[]args){MyJOptionPanedialog=newMyJOptionPane();if(dialog.showConfirm())System.out.println("Clicou no sim!");elseSystem.out.println("Não clicou no sim!");}}
Se você irá usar o JOptionPane dessa forma, aí não teria porque criar outra janela inteira.
V
victorp_farias
Bem o que eu realmente queria era um JOptionPane que os botões respondesem pelas teclas “S” e “N” sem usar o alt.
A solução que eu encontrei foi usar o InputMap e ActionMap, já que não consegui fazer eles fucionarem no JOptionPane fiz no JDialog.
Para ficar mais parecido visualmente com o JOptionPane nada melhor que passar o próprio JOptionPane. Entende?
De qualquer modo foram exelente as digas para melhor organizar a classe, especialmente as do Action, grato.
ViniGodoy
Sim, mas você nem sempre terá esse recurso, você pode querer fazer um dialog bem mais complexo, como deixar o usuário escolher um valor numa JTable, por exemplo. Como não tinha como saber se você estava sabendo ou não o que estava fazendo, achei mais prudente colocar o código da interface gráfica completa.