別のJFrame
で参照したいJFrame
いくつかのコンポーネントがあり、それらを名前で取得し、それぞれに対してパブリックget/setメソッドを実行したくない。
Swingから、c#のような名前でコンポーネント参照を取得する方法はありますか?
例えばform.Controls["text"]
ありがとう
私はこれが古い質問であることを知っていますが、私はたった今それを尋ねていることに気づきました。名前でコンポーネントを取得する簡単な方法が欲しかったので、さまざまなコンポーネントにアクセスするために毎回複雑なコードを記述する必要がありませんでした。たとえば、JButtonにテキストフィールドのテキストまたはリストの選択にアクセスさせる。
最も簡単な解決策は、すべてのコンポーネント変数をクラス変数にして、どこからでもアクセスできるようにすることです。ただし、誰もがそれを望んでいるわけではなく、一部(私のような)は、コンポーネントをクラス変数として生成しないGUIエディターを使用しています。
私の解決策は単純です。考えたいのですが、私が知る限り(プログラミングの標準がFortranで達成されていることを参照)違反していません。名前を使用してコンポーネントにアクセスする簡単で簡単な方法が可能になります。
Mapクラス変数を作成します。少なくともHashMapをインポートする必要があります。わかりやすくするために、私は私のコンポーネントマップに名前を付けました。
private HashMap componentMap;
通常どおり、すべてのコンポーネントをフレームに追加します。
initialize() {
//add your components and be sure
//to name them.
...
//after adding all the components,
//call this method we're about to create.
createComponentMap();
}
クラスで次の2つのメソッドを定義します。まだインポートしていない場合は、コンポーネントをインポートする必要があります。
private void createComponentMap() {
componentMap = new HashMap<String,Component>();
Component[] components = yourForm.getContentPane().getComponents();
for (int i=0; i < components.length; i++) {
componentMap.put(components[i].getName(), components[i]);
}
}
public Component getComponentByName(String name) {
if (componentMap.containsKey(name)) {
return (Component) componentMap.get(name);
}
else return null;
}
これで、フレーム、コンテンツペイン、パネルなどに現在存在するすべてのコンポーネントをそれぞれの名前にマッピングするHashMapができました。
これらのコンポーネントにアクセスするには、getComponentByName(String name)を呼び出すだけです。その名前のコンポーネントが存在する場合、そのコンポーネントを返します。そうでない場合は、nullを返します。コンポーネントを適切なタイプにキャストするのはユーザーの責任です。確かにinstanceofを使用することをお勧めします。
実行時の任意の時点でコンポーネントを追加、削除、または名前変更する予定がある場合は、変更に応じてHashMapを変更するメソッドを追加することを検討します。
各 Component
には名前を付けることができ、getName()
およびsetName()
を介してアクセスできますが、独自のルックアップ関数を作成する必要があります。
getComponentByName(フレーム、名前)
NetBeansまたは別のIDEを使用している場合、デフォルトですべてのAWT/Swingコンポーネントを保持するプライベート変数(フィールド)が作成されます)、次のコードが機能する場合があります。次のように使用します。
// get a button (or other component) by name
JButton button = Awt1.getComponentByName(someOtherFrame, "jButton1");
// do something useful with it (like toggle it's enabled state)
button.setEnabled(!button.isEnabled());
これを可能にするコードは次のとおりです...
import Java.awt.Component;
import Java.awt.Window;
import Java.lang.reflect.Field;
/**
* additional utilities for working with AWT/Swing.
* this is a single method for demo purposes.
* recommended to be combined into a single class
* module with other similar methods,
* e.g. MySwingUtilities
*
* @author http://javajon.blogspot.com/2013/07/Java-awtswing-getcomponentbynamewindow.html
*/
public class Awt1 {
/**
* attempts to retrieve a component from a JFrame or JDialog using the name
* of the private variable that NetBeans (or other IDE) created to refer to
* it in code.
* @param <T> Generics allow easier casting from the calling side.
* @param window JFrame or JDialog containing component
* @param name name of the private field variable, case sensitive
* @return null if no match, otherwise a component.
*/
@SuppressWarnings("unchecked")
static public <T extends Component> T getComponentByName(Window window, String name) {
// loop through all of the class fields on that form
for (Field field : window.getClass().getDeclaredFields()) {
try {
// let us look at private fields, please
field.setAccessible(true);
// compare the variable name to the name passed in
if (name.equals(field.getName())) {
// get a potential match (assuming correct <T>ype)
final Object potentialMatch = field.get(window);
// cast and return the component
return (T) potentialMatch;
}
} catch (SecurityException | IllegalArgumentException
| IllegalAccessException ex) {
// ignore exceptions
}
}
// no match found
return null;
}
}
リフレクションを使用してクラスフィールドを調べ、同じ名前の変数によって参照されるコンポーネントを見つけることができるかどうかを確認します。
注:上記のコードはジェネリックスを使用して、結果を予想される型にキャストするため、場合によっては型キャストについて明示的にする必要があります。たとえば、myOverloadedMethod
がJButton
とJTextField
の両方を受け入れる場合、呼び出すオーバーロードを明示的に定義する必要があるかもしれません...
myOverloadedMethod((JButton) Awt1.getComponentByName(someOtherFrame, "jButton1"));
わからない場合は、Component
を取得してinstanceof
...で確認できます。
// get a component and make sure it's a JButton before using it
Component component = Awt1.getComponentByName(someOtherFrame, "jButton1");
if (component instanceof JButton) {
JButton button = (JButton) component;
// do more stuff here with button
}
お役に立てれば!
最初のJFrameへの参照を2番目のJFrameに保持し、JFrame.getComponents()をループして、各要素の名前を確認することができます。
単一のJPanel
内にある複数のJFrame
s内の要素にアクセスする必要がありました。
@Jesse Stricklandは素晴らしい回答を投稿しましたが、提供されたコードはネストされた要素(私の場合のようにJPanel
内)にアクセスできません。
追加のグーグル検索の後、@ aioobe here によって提供されるこの再帰的なメソッドを見つけました。
@Jesse Stricklandと@aioobeのコードを組み合わせて少し変更することで、ネストされたすべての要素にアクセスできる実際のコードが得られます。
private void createComponentMap() {
componentMap = new HashMap<String,Component>();
List<Component> components = getAllComponents(this);
for (Component comp : components) {
componentMap.put(comp.getName(), comp);
}
}
private List<Component> getAllComponents(final Container c) {
Component[] comps = c.getComponents();
List<Component> compList = new ArrayList<Component>();
for (Component comp : comps) {
compList.add(comp);
if (comp instanceof Container)
compList.addAll(getAllComponents((Container) comp));
}
return compList;
}
public Component getComponentByName(String name) {
if (componentMap.containsKey(name)) {
return (Component) componentMap.get(name);
}
else return null;
}
コードの使用方法は、@ Jesse Stricklandコードとまったく同じです。
変数をパブリック変数として宣言し、テキストまたは必要な操作を取得し、パブリックであるため、他のフレーム(同じパッケージ内にある場合)でその変数にアクセスできます。
コンポーネントを操作しているのと同じクラス内で宣言した場合は、これらのコンポーネントにクラス名の属性としてアクセスするだけです。
public class TheDigitalClock {
private static ClockLabel timeLable = new ClockLabel("timeH");
private static ClockLabel timeLable2 = new ClockLabel("timeM");
private static ClockLabel timeLable3 = new ClockLabel("timeAP");
...
...
...
public void actionPerformed(ActionEvent e)
{
...
...
...
//set all components transparent
TheDigitalClock.timeLable.setBorder(null);
TheDigitalClock.timeLable.setOpaque(false);
TheDigitalClock.timeLable.repaint();
...
...
...
}
...
...
...
}
そして、あなたはmayクラス名の属性としてクラスコンポーネントにアクセスできる同じ名前空間の他のクラスからも。保護された属性(クラスメンバー変数)にアクセスできます。パブリックコンポーネントにもアクセスできます。それを試してみてください!