2017-07-29 79 views
0

最近、Java + SwingでUIを構築する作業を開始しました。現在、JTextFieldをFlowLayoutでJPanelに配置して問題が発生しています。Swing:JPanel内のJTextField、再描画の問題

私の例では、ボタン付きのパネルを含むウィンドウがあります。このボタンをクリックすると、JTextFieldを含むJPanelから派生したコンポーネントが追加されます。

問題は、JTextFieldに入力すると更新されない(サイズが変更されない)ということです。しかし、ウィンドウのサイズを変更したり、ウィンドウ/パネルの再描画を強制する他の操作を行うと、テキストフィールドのサイズが変更されます(私は自動的に何が起こるか)。

基本クラスをJPanelからJTextFieldに変更すると、これは達成しようとする方法で機能しますが、子コンポーネントを置く利点を得るために、JPanelを基本クラスとして持つ必要があります。

私はここで別の問題をチェックしているだけでなく、Googleが解決策を見つけようとしているが、私にとってはうまくいかなかった。私はvalidate/invalidate/revalidate/repaintをさまざまな組み合わせで試してみましたが、それぞれの型付けされた文字の再検証を強制しようとしています。これまでのところ、レイアウトマネージャとは関係があります。

スイングUI、レイアウト管理、再描画がどのように機能しているのか、私はそのことがどのように機能するのか理解してもらえますか?

また、自分のコードに関する特定の問題について誰かが私を助けることができたらうれしいです。

ありがとうございます!ここで

は、以下の私のコードです:

import javax.swing.*; 
import java.awt.*; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 


class TagVisual extends JPanel /*JTextField*/ { 

    private JTextField editField; 

    public TagVisual() { 

     FlowLayout layout = new FlowLayout(); 
     layout.setHgap(0); 
     layout.setVgap(0); 
     setLayout(layout); 

     editField = new JTextField(); 
     editField.setBackground(Color.RED); 

     editField.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent e) { 
       editField.setSize(editField.getSize()); 
       editField.revalidate(); 
       remove(editField); 
       add(editField); 
       revalidate(); 
       repaint(); 
      } 
     }); 

     add(editField, FlowLayout.LEFT); 
    } 

    public void place(JPanel panel) { 
     panel.add(this); 

     editField.grabFocus(); 
    } 
} 

public class MainWindow { 

    private JPanel mainPanel; 
    private JButton btnPlace; 
    private JFrame frame; 

    public MainWindow(JFrame frame) { 

     mainPanel = new JPanel(new FlowLayout()); 
     btnPlace = new JButton(); 
     btnPlace.setText("Place"); 
     mainPanel.add(btnPlace); 

     this.frame = frame; 
     btnPlace.addActionListener(new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent e) { 
       TagVisual v = new TagVisual(); 
       v.place(mainPanel); 
       mainPanel.revalidate(); 
       mainPanel.repaint(); 
       mainPanel.updateUI(); 
       frame.revalidate(); 
       frame.repaint(); 
      } 
     }); 
    } 

    public static void main(String[] args) { 
     JFrame frame = new JFrame("TextFieldUpdateIssue"); 

     frame.setContentPane(new MainWindow(frame).mainPanel); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.pack(); 
     frame.setVisible(true); 
    } 
} 
+0

したがって、入力したテキストに基づいてテキストフィールドのサイズを大きくしたいですか?これは正常な動作ではありません。ユーザーは私が非常に厄介なことに気付くでしょう... – Ansharja

+0

はい、それは私が欲しいものです。私は入力時にサイズが大きくなることが予想されるタグエディタコンポーネントを作成しています。 –

+0

ようこそ。投稿する[mcve]。このコードは実行されません( 'btnPlace'と' mainPanel'は決して初期化されず、フレームに追加されません)。 – c0der

答えて

1

私があなただったら、私は、ユーザーがいくつかに入ったときにテキストフィールドのサイズを変更しようとしないだろうテキスト。

JTextField(int columns)コンストラクタを使用してそれらを固定サイズにすることをお勧めします。これにより、「十分に広い」テキストフィールドをいくつか作成することができます。

テキストが入力されたときにそれらをさらに広げたい場合は、入力されたテキストに基づいているのではなく、Enterキーを押したときにイベントを発生させるため、ActionListenerを使用できません。

この目的のために、テキストフィールドの文書にDocument Listenerを登録することができます。

getPreferredSize()メソッドをオーバーライドして、適切なサイズを計算して返すこともできます。以下の例では、わかりやすい幅を計算するためにJLabelを使用していますが、FontMetricsを使用することもできます。

複数のタグをパネルに追加する場合は、さらにスペースが必要なときにスクロールバーを表示するために、JScrollPaneを使用することを検討する必要があります。

import java.awt.*; 
import java.awt.event.*; 
import javax.swing.*; 
import javax.swing.event.*; 
public class MainWindow 
{ 
    public static void main (String [] a) { 
     SwingUtilities.invokeLater (new Runnable() { 
      @Override public void run() { 
       try { 
        UIManager.setLookAndFeel (UIManager.getSystemLookAndFeelClassName()); 
        createAndShowGUI(); 
       } 
       catch (Exception e) { 
        JOptionPane.showMessageDialog (null, "An unexpected error occurred: " + e.getClass().getSimpleName(), "Error", JOptionPane.ERROR_MESSAGE); 
       } 
      } 
     }); 
    } 
    private static void createAndShowGUI() { 
     JFrame frame = new JFrame ("TextFieldUpdateIssue"); 
     frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE); 
     frame.setContentPane (new MainPanel()); 
     frame.setExtendedState (JFrame.MAXIMIZED_BOTH); 
     frame.setLocationRelativeTo (null); 
     frame.setVisible (true); 
    } 
} 
class MainPanel extends JPanel 
{ 
    private JPanel tagsPanel; 

    public MainPanel() { 
     super (new BorderLayout (0, 10)); 
     add (new JButton (new AbstractAction ("Add tag") { 
      @Override public void actionPerformed(ActionEvent e) { 
       addNewTag(); 
      } 
     }), BorderLayout.NORTH); 
     tagsPanel = new JPanel(); 
     tagsPanel.setLayout (new FlowLayout (FlowLayout.CENTER, 10, 0)); 
     add (tagsPanel, BorderLayout.CENTER); 
    } 
    private void addNewTag() { 
     TagVisual v = new TagVisual(); 
     tagsPanel.add (v); 
     v.grabFocusOnField(); 
     revalidate(); 
    } 
} 
class TagVisual extends JPanel 
{ 
    private JTextField editField; 

    public TagVisual() { 
     super (new FlowLayout (FlowLayout.CENTER, 0, 0)); 
     add (editField = createNewTextField (null), FlowLayout.LEFT); 
    } 
    private JTextField createNewTextField (String text) { 
     JTextField textField = new JTextField (text) { 
      @Override public Dimension getPreferredSize() { 
       Dimension d = super.getPreferredSize(); 
       return new Dimension (new JLabel (getText()).getPreferredSize().width + 10, d.height); 
      } 
     }; 
     textField.setBackground (Color.RED); 
     textField.getDocument().addDocumentListener (new DocumentListener() { 
      @Override public void changedUpdate (DocumentEvent e) { 
       revalidate(); 
      } 
      @Override public void insertUpdate (DocumentEvent e) { 
       revalidate(); 
      } 
      @Override public void removeUpdate (DocumentEvent e) { 
       revalidate(); 
      } 
     }); 
     return textField; 
    } 
    public void grabFocusOnField() { 
     editField.grabFocus(); 
     editField.setCaretPosition (editField.getText().length()); 
    } 
} 

スクリーンショット(ショートテキスト:

は(今私はそれが優れていると思いますが、いないまだ良い、それがコンパイルされないでしょうので、私はあなたのコードビットを変更し、一般的な設計が悪かった)この例を参照してください。 ):

enter image description here

スクリーン(長いテキスト):

enter image description here

0

コードを確認して、コメントを注意してください。

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.FlowLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JTextField; 

public class MainWindow { 

    private JPanel mainPanel; 
    private JButton btnPlace; 

    public MainWindow(){ 

     JFrame frame = new JFrame("TextFieldUpdateIssue"); 
     //you can't use components before initializing them 
     btnPlace = new JButton("Button"); 
     frame.add(btnPlace, BorderLayout.NORTH); 
     mainPanel = new JPanel(); 
     frame.add(mainPanel, BorderLayout.CENTER); 
     btnPlace.addActionListener(new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent e) { 
       TagVisual v = new TagVisual(); 
       mainPanel.add(v); //add it to main panel 
       //v.place(mainPanel); 
       //mainPanel.revalidate(); 
       //mainPanel.repaint(); 
       //mainPanel.updateUI(); 
       //frame.revalidate(); 
       //frame.repaint(); 
       frame.pack(); 
      } 
     }); 

     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.pack(); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 

     new MainWindow(); 
    } 
} 

class TagVisual extends JPanel /*JTextField*/ { 

    private JTextField editField; 

    public TagVisual() { 

     FlowLayout layout = new FlowLayout(); 
     layout.setHgap(0); 
     layout.setVgap(0); 
     setLayout(layout); 

     editField = new JTextField(); 
     //give it a preferred size to be used by layout manager 
     editField.setPreferredSize(new Dimension(150,25)); 
     editField.setBackground(Color.RED); 

     editField.addActionListener(new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent e) { 
       //not sure what you want to do here 
       //not relevant to the question 
      } 
     }); 

     add(editField, FlowLayout.LEFT); 
    } 
} 
+2

'' //レイアウトマネージャが使用するのに適したサイズを与えてください。」 - テキストコンポーネントとはまったく関係がありません。コンポーネントの本来の振る舞いを酷評する楽器です。フォントと列のプロパティを設定することで、「サイズを設定する」方がはるかに優れています。たとえば、コンポーネントがJScrollPane内にある場合、そのコンポーネントは正しく動作しないことを保証します。 –

+0

ありがとう、ここで説明したJTextFieldの自動サイズ設定を適用してくれてありがとうございました。https://stackoverflow.com/questions/22128813/set-a-jtextfield-width-in-maner-to-wrap-a-given-text –

関連する問題