Не удается редактировать текст JTextField внутри JPanel в JWindow
Это продолжение моего предыдущего вопроса, где я спросил, как разместить что-то в системном трее.
После некоторой помощи от сообщества, я мог сделать это. Однако я не могу изменить текст JTextField
в JWindow
,
JWindow
имеет JPanel
и все находится внутри JPanel
, в том числе JTextField
Напомнить Mt At. Однако я не могу ничего в нем набрать, хотя setEditable(true)
,JTextField
получает события правильно, так как он должен быть белым, когда мышь входит, и возвращаться к цвету по умолчанию, когда мышь выходит.
Есть ли обходной путь для этого?
SSCCE
package demo;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.InputStream;
import javax.imageio.ImageIO;
import javax.sound.sampled.*;
import javax.swing.*;
import javax.swing.border.BevelBorder;
import example.Kernel32;
public class SSCCE {
JPopupMenu popup = new JPopupMenu();
JMenuItem exit = new JMenuItem("Exit");
JWindow window = new JWindow();
JPanel panel = new JPanel();
int remindMeAt = 55;
Kernel32.SYSTEM_POWER_STATUS batteryStatus = new Kernel32.SYSTEM_POWER_STATUS();
Clip buzzer;
AudioInputStream in;
JLabel ACLineStatus = new JLabel();
JLabel batteryCharge = new JLabel();
JTextField enterReminder = new JTextField(3);
Color defaultColor;
String onACPower;
String charge;
String status;
boolean keepLooping = true;
boolean doRemind = true;
boolean isCharging;
boolean aboveThreshold;
boolean remindedOnce = false;
//------------------------------------------------------------------------------
public static void main(String[] args) {
new SSCCE();
}
//------------------------------------------------------------------------------
public SSCCE(){
if(SystemTray.isSupported()){
setupGUI();
}
}
//------------------------------------------------------------------------------
public void setupGUI(){
try{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
InputStream in = BatteryBeeperSystemTray.class.
getResourceAsStream("/images/battery_smaller.png");
TrayIcon t = new TrayIcon(ImageIO.read(in));
t.setToolTip("BatteryBeeper");
SystemTray.getSystemTray().add(t);
}catch(Exception e){
}
panel.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
defaultColor = window.getBackground();
Kernel32.INSTANCE.GetSystemPowerStatus(batteryStatus);
onACPower = batteryStatus.getACLineStatusString();
charge = batteryStatus.getBatteryLifePercent();
if(onACPower.equalsIgnoreCase("offline")){
onACPower = "Battery";
}else{
onACPower = "AC Power";
charge = "---";
}
ACLineStatus.setText(onACPower);
ACLineStatus.setPreferredSize(new Dimension(150,40));
ACLineStatus.setBorder(BorderFactory.createTitledBorder("Operating On"));
gbc.gridx = 0;
gbc.gridy = 0;
gbc.gridwidth = 7;
gbc.gridheight = 1;
gbc.fill = GridBagConstraints.BOTH;
panel.add(ACLineStatus,gbc);
batteryCharge.setText(charge);
batteryCharge.setBorder(BorderFactory.createTitledBorder("Current " +
"Charge"));
gbc.gridy++;
panel.add(batteryCharge,gbc);
panel.setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED));
gbc.gridy++;
enterReminder.setEditable(true);
enterReminder.requestFocusInWindow();
enterReminder.setText(Integer.toString(remindMeAt));
enterReminder.addMouseListener(new TextHandler());
enterReminder.setBackground(window.getBackground());
enterReminder.setBorder(BorderFactory.createTitledBorder("Remind Me" +
" At"));
panel.add(enterReminder,gbc);
window.add(panel);
window.pack();
window.setLocationRelativeTo(null);
window.setVisible(true);
}
//------------------------------------------------------------------------------
public void checkIfReminderChanged(){
//TODO DEFINE
}
//------------------------------------------------------------------------------
public class TextHandler extends MouseAdapter{
@Override
public void mouseEntered(MouseEvent e){
enterReminder.setBackground(Color.WHITE);
}
//------------------------------------------------------------------------------
@Override
public void mouseExited(MouseEvent e){
enterReminder.setBackground(defaultColor);
checkIfReminderChanged();
}
}
//------------------------------------------------------------------------------
}
Что вам тоже нужно
package example;
import com.sun.jna.Native;
import com.sun.jna.Structure;
import com.sun.jna.win32.StdCallLibrary;
import java.util.*;
public interface Kernel32 extends StdCallLibrary {
public Kernel32 INSTANCE = (Kernel32) Native.loadLibrary("Kernel32", Kernel32.class);
/**
* @see http://msdn2.microsoft.com/en-us/library/aa373232.aspx
*/
public class SYSTEM_POWER_STATUS extends Structure {
public byte ACLineStatus;
public byte BatteryFlag;
public byte BatteryLifePercent;
public byte Reserved1;
public int BatteryLifeTime;
public int BatteryFullLifeTime;
@Override
protected List<String> getFieldOrder() {
ArrayList<String> fields = new ArrayList<String>();
fields.add("ACLineStatus");
fields.add("BatteryFlag");
fields.add("BatteryFullLifeTime");
fields.add("BatteryLifePercent");
fields.add("BatteryLifeTime");
fields.add("Reserved1");
return fields;
}
/**
* The AC power status
*/
public String getACLineStatusString() {
switch (ACLineStatus) {
case (0): return "Offline";
case (1): return "Online";
default: return "Unknown";
}
}
/**
* The battery charge status
*/
public String getBatteryFlagString() {
switch (BatteryFlag) {
case (1): return "High, more than 66 percent";
case (2): return "Low, less than 33 percent";
case (4): return "Critical, less than five percent";
case (8): return "Charging";
case ((byte) 128): return "No system battery";
default: return "Unknown";
}
}
/**
* The percentage of full battery charge remaining
*/
public String getBatteryLifePercent() {
return (BatteryLifePercent == (byte) 255) ? "Unknown" : BatteryLifePercent + "%";
}
/**
* The number of seconds of battery life remaining
*/
public String getBatteryLifeTime() {
return (BatteryLifeTime == -1) ? "Unknown" : BatteryLifeTime + " seconds";
}
/**
* The number of seconds of battery life when at full charge
*/
public String getBatteryFullLifeTime() {
return (BatteryFullLifeTime == -1) ? "Unknown" : BatteryFullLifeTime + " seconds";
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("ACLineStatus: " + getACLineStatusString() + "\n");
sb.append("Battery Flag: " + getBatteryFlagString() + "\n");
sb.append("Battery Life: " + getBatteryLifePercent() + "\n");
sb.append("Battery Left: " + getBatteryLifeTime() + "\n");
sb.append("Battery Full: " + getBatteryFullLifeTime() + "\n");
return sb.toString();
}
}
public int GetSystemPowerStatus(SYSTEM_POWER_STATUS result);
}
4 ответа
В спецификации говорится о isFocusableWindow()
как показано ниже (я добавил нумерацию, чтобы очертить точки):
открытый финальный логический isFocusableWindow()
Возвращает, может ли это окно стать сфокусированным окном, то есть может ли это окно или любой из его подкомпонентов стать владельцем фокуса. Для того, чтобы фрейм или диалог могли быть фокусируемыми, его фокусируемое состояние окна должно быть установлено в true. Для окна, которое не является рамкой или диалоговым окном, для фокусировки,
i) его фокусируемое состояние окна должно быть установлено в true,
ii) его ближайший владелец Frame или Dialog должен отображаться на экране,
iii) и он должен содержать хотя бы один компонент в цикле обхода фокуса.
Если какое-либо из этих условий не выполняется, то ни это Окно, ни какой-либо из его подкомпонентов не могут стать владельцем фокуса.
Как видите, ваш код не соответствует второму правилу, поэтому ваш JWindow
не фокусируется Вам нужно иметь JDialog
или же JFrame
отображается на экране, а затем вы можете обернуть его JWindow
:
new JWindow(frame);
Или вы можете использовать JDialog
или же JFrame
прямо вместо JWindow
, Если вы не хотите, чтобы окно было украшено, просто позвоните Frame.setUndecorated(true)
или же Dialog.setUndecorated(true)
,
Создать JWindow, как это
JWindow window = new JWindow(new JFrame(){public boolean isShowing(){return true;}});
Не используется настройка "setEditable(true)", потому что по умолчанию setEditable имеет значение true в JTextField. Что "requestFocusInWindow()" делает в вашем коде. Я подозреваю, что проблема там.. не совсем уверен...
Я не эксперт, но код выглядит хорошо. Единственное предложение, которое у меня есть, это использовать другой компонент, который похож на JTextField
,
Попробуйте использовать JTextArea
вместо. Другие компоненты, такие как JTextField
а также JTextPane
Также могут быть варианты. Все они существуют в javax.swing
библиотека, чтобы использовать его import javax.swing.*