Java JTextFieldUI以我个人的外观和感觉绘制在JTabbedPane的另一个选项卡中
我正在开发一种新的外观,现在我在JTAbblePane组件中使用组件JtextField时遇到了一个错误 问题是这个 我的JTextFieldUI有这个代码,它扩展了BasicLookAndFellJava JTextFieldUI以我个人的外观和感觉绘制在JTabbedPane的另一个选项卡中,java,swing,look-and-feel,jtabbedpane,Java,Swing,Look And Feel,Jtabbedpane,我正在开发一种新的外观,现在我在JTAbblePane组件中使用组件JtextField时遇到了一个错误 问题是这个 我的JTextFieldUI有这个代码,它扩展了BasicLookAndFell public class MyPersonalFieldUI extends BasicTextFieldUI { protected static final String PROPERTY_LINE_COLOR = "lineColor"; protected static
public class MyPersonalFieldUI extends BasicTextFieldUI {
protected static final String PROPERTY_LINE_COLOR = "lineColor";
protected static final String PROPERTY_SELECTION_COLOR = "selectionColor";
protected static final String PROPERTY_SELECTION_TEXT_COLOR = "selectedTextColor";
protected static final String ProprietyPrefix = "TextField";
protected boolean drawLine;
protected JTextComponent textComponent;
protected Color background;
protected Color foreground;
protected Color activeBackground;
protected Color activeForeground;
protected Color inactiveBackground;
protected Color inactiveForeground;
protected Color colorLineInactive;
protected Color colorLineActive;
protected Color colorLine;
protected FocusListener focusListenerColorLine;
protected PropertyChangeListener propertyChangeListener;
protected PropertyChangeSupport propertyChangeSupport;
public MyPersonalFieldUI() {
this(true);
}
public MyPersonalFieldUI(boolean drawLine) {
super();
this.drawLine = drawLine;
this.focusListenerColorLine = new FocusListenerColorLine();
this.propertyChangeListener = new MaterialPropertyChangeListener();
this.propertyChangeSupport = new PropertyChangeSupport(this);
}
@Override
protected String getPropertyPrefix() {
return ProprietyPrefix;
}
public static ComponentUI createUI(JComponent c) {
return new MyPersonalFieldUI();
}
@Override
public void installUI(JComponent c) {
super.installUI(c);
this.textComponent = (JTextField) c;
}
@Override
protected void installDefaults() {
super.installDefaults();
installMyDefaults();
}
@Override
public void uninstallUI(JComponent c) {
super.uninstallUI(c);
c.setFont(null);
c.setBackground(null);
c.setForeground(null);
c.setBorder(null);
c.setCursor(null);
}
@Override
protected void uninstallDefaults() {
super.uninstallDefaults();
getComponent().setBorder(null);
}
@Override
protected void installListeners() {
super.installListeners();
getComponent().addFocusListener(focusListenerColorLine);
getComponent().addPropertyChangeListener(propertyChangeListener);
propertyChangeSupport.addPropertyChangeListener(propertyChangeListener);
}
@Override
protected void uninstallListeners() {
getComponent().removeFocusListener(focusListenerColorLine);
getComponent().removePropertyChangeListener(propertyChangeListener);
propertyChangeSupport.removePropertyChangeListener(propertyChangeListener);
super.uninstallListeners();
}
@Override
public void paintSafely(Graphics g) {
super.paintSafely(g);
paintLine(g);
}
protected void logicForChangeColorOnFocus(JComponent component, Color background, Color foreground) {
if (background == null || foreground == null) {
return;
}
JTextField textField = (JTextField) component;
if (!this.activeForeground.equals(foreground)) { //TODO this comment resolve the issue but I don't not if it introduce some bug
textField.setSelectedTextColor(inactiveForeground);
} else {
textField.setSelectedTextColor(foreground);
}
textField.setSelectionColor(background);
}
protected void installMyDefaults() {
this.background = UIManager.getColor(getPropertyPrefix() + ".background");
this.foreground = UIManager.getColor(getPropertyPrefix() + ".foreground");
this.activeBackground = UIManager.getColor(getPropertyPrefix() + ".selectionBackground");
this.activeForeground = UIManager.getColor(getPropertyPrefix() + ".selectionForeground");
this.inactiveBackground = UIManager.getColor(getPropertyPrefix() + ".inactiveBackground");
this.inactiveForeground = UIManager.getColor(getPropertyPrefix() + ".inactiveForeground");
colorLineInactive = UIManager.getColor(getPropertyPrefix() + "[Line].inactiveColor");
colorLineActive = UIManager.getColor(getPropertyPrefix() + "[Line].activeColor");
getComponent().setFont(UIManager.getFont(getPropertyPrefix() + ".font"));
colorLine = getComponent().hasFocus() && getComponent().isEditable() ? colorLineActive : colorLineInactive;
getComponent().setSelectionColor(getComponent().hasFocus() && getComponent().isEnabled() ? activeBackground : inactiveBackground);
getComponent().setSelectedTextColor(getComponent().hasFocus() && getComponent().isEnabled() ? activeForeground : inactiveForeground);
getComponent().setForeground(getComponent().hasFocus() && getComponent().isEnabled() ? activeForeground : inactiveForeground);
getComponent().setBorder(UIManager.getBorder(getPropertyPrefix() + ".border"));
}
protected void logicForPropertyChange(Color newColor, boolean isForeground) {
if (newColor == null) {
return;
}
if (isForeground && (!newColor.equals(activeForeground) && !newColor.equals(inactiveForeground))) {
this.activeForeground = newColor;
getComponent().repaint();
}
if (!isForeground && !newColor.equals(activeBackground) && !newColor.equals(inactiveBackground)) {
this.activeBackground = newColor;
getComponent().repaint();
}
}
protected void changeColorOnFocus(boolean hasFocus) {
JTextComponent c = getComponent();
if (c == null) {
return;
}
if (hasFocus && (activeBackground != null) && (activeForeground != null)) {
logicForChangeColorOnFocus(c, activeBackground, activeForeground);
//TODO create a new changePropriety
paintLine(c.getGraphics());
}
if (!hasFocus && (inactiveBackground != null) && (inactiveForeground != null)) {
logicForChangeColorOnFocus(c, inactiveBackground, inactiveForeground);
paintLine(c.getGraphics());
}
if (c.getGraphics() != null) {
c.paint(c.getGraphics());
}
}
protected synchronized void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
if ((propertyName == null || propertyName.isEmpty()) || oldValue == null || newValue == null) {
throw new IllegalArgumentException("Some property null");
}
//TODO refectoring this code
if (propertyChangeSupport == null || (oldValue != null && newValue != null && oldValue.equals(newValue))) {
return;
}
if (propertyChangeSupport == null || oldValue == newValue) {
return;
}
propertyChangeSupport.firePropertyChange(propertyName, oldValue, newValue);
}
protected void paintLine(Graphics graphics) {
if (graphics == null) {
return;
}
JTextComponent c = getComponent();
if (drawLine) {
int x = c.getInsets().left;
int y = c.getInsets().top;
int w = c.getWidth() - c.getInsets().left - c.getInsets().right;
graphics.setColor(colorLine);
graphics.fillRect(x, c.getHeight() - y, w, 1);
}
}
protected class FocusListenerColorLine implements FocusListener {
@Override
public void focusGained(FocusEvent e) {
firePropertyChange(PROPERTY_LINE_COLOR, colorLineInactive, colorLineActive);
changeColorOnFocus(true);
}
@Override
public void focusLost(FocusEvent e) {
firePropertyChange(PROPERTY_LINE_COLOR, colorLineActive, colorLineInactive);
changeColorOnFocus(false);
}
}
protected class MaterialPropertyChangeListener implements PropertyChangeListener {
@Override
public void propertyChange(PropertyChangeEvent pce) {
if (getComponent() == null) {
return;
}
if (pce.getPropertyName().equals(PROPERTY_SELECTION_COLOR)) {
Color newColor = (Color) pce.getNewValue();
logicForPropertyChange(newColor, false);
}
if (pce.getPropertyName().equals(PROPERTY_SELECTION_TEXT_COLOR)) {
Color newColor = (Color) pce.getNewValue();
logicForPropertyChange(newColor, true);
}
if (pce.getPropertyName().equals(PROPERTY_LINE_COLOR)) {
Color newColor = (Color) pce.getNewValue();
colorLine = newColor;
getComponent().repaint();
}
if (pce.getPropertyName().equals("background")) {
getComponent().repaint();
}
}
}
}
对不起,我的大代码,但我认为是必要的,以找到我的错误里面
另外,这是我的最小可复制示例
public class DemoLookAndFeel extends JFrame {
static {
try {
UIManager.setLookAndFeel(new MyLookAndFeel());
} catch (UnsupportedLookAndFeelException ex) {
}
}
public void init() {
JPanel panelOne = new JPanel();
panelOne.add(new JTextField("write inside me and change the tab"));
JPanel panelTwo = new JPanel();
//panelTwo.add(new Label("Now seee the JTextField?"));
JTabbedPane tabbedPane = new JTabbedPane();
tabbedPane.add("One", panelOne);
tabbedPane.add("Two", panelTwo);
this.setContentPane(tabbedPane);
this.setSize(800,800);
this.pack();
this.setLocationRelativeTo(null);
this.setVisible(true);
}
private static class MyLookAndFeel extends BasicLookAndFeel {
@Override
public String getName() {
return "my look and feel";
}
@Override
public String getID() {
return "qwerty";
}
@Override
public String getDescription() {
return "";
}
@Override
public boolean isNativeLookAndFeel() {
return false;
}
@Override
public boolean isSupportedLookAndFeel() {
return true;
}
@Override
protected void initClassDefaults(UIDefaults table) {
super.initClassDefaults(table);
table.put("TextFieldUI", MyPersonalFieldUI.class.getCanonicalName());
}
@Override
protected void initSystemColorDefaults(UIDefaults table) {
super.initSystemColorDefaults(table);
table.put("TextField.background", Color.GRAY);
table.put("TextField.foreground", Color.BLACK);
table.put("TextField.inactiveForeground", Color.BLACK);
table.put("TextField.inactiveBackground", Color.GRAY);
table.put("TextField.selectionBackground", Color.BLUE);
table.put("TextField.selectionForeground", Color.WHITE);
table.put("TextField[Line].inactiveColor", Color.WHITE);
table.put("TextField[Line].activeColor", Color.BLUE);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
DemoLookAndFeel demo = new DemoLookAndFeel();
demo.init();
}
});
}
}
ps:对不起,我的代码太大了问题在于如何操作绘画。在
changeColorOnFocus
(由FocusListener
调用)方法中,您有以下几行代码:
if (c.getGraphics() != null) {
c.paint(c.getGraphics());
}
在这里,您使用图形并在负责在“组件绘制继承人”中绘制的方法之外进行一种自定义绘制。我希望我能更好地解释它,但长话短说,只在将它们作为参数的方法中使用图形
(并称其为超级
方法)。在UI
类中,方法是paintsafe
,在组件中是paintComponent
。它们都为您提供图形
对象,因此它们适合于自定义绘制
因此,解决方案位于FocusListener
中,添加一个标志以了解组件是否已聚焦,并在paintsafe(Graphics g)
方法中调用changeColorOnFocus
。您的UI类应该在以下部分进行更改(我不会全部粘贴,因为它有点大)
预览:
对不起,我只能向上投票,如果你愿意,你能更好地解释这个问题吗?@vincenzopalazzo我希望我知道如何更好地解释它。考虑一下:为了绘制组件,API调用方法a、B和C。如果您在这些方法之外绘制,您将遇到问题,因为它不在顺序中。因此,您必须重写其中一个方法才能“进入序列”。因此,我们更喜欢重写C方法,以便最后进行自定义绘制。(1-)交叉发布:tab JTabbedPane personal。所以你有一个答案。为什么你没有更新你的另一个问题,表明你找到了答案,这样人们就不会花时间回答一个已经有答案的问题?@camickr我一回到家就会这么做,因为我没有电脑,在其他场合,我总是更新我的问题,以防在其他论坛上找到解决方案。我只是需要一些时间,几个小时的问题,对不起
private boolean focused; //a field
protected class FocusListenerColorLine implements FocusListener {
@Override
public void focusGained(FocusEvent e) {
firePropertyChange(PROPERTY_LINE_COLOR, colorLineInactive, colorLineActive);
focused = true;
}
@Override
public void focusLost(FocusEvent e) {
firePropertyChange(PROPERTY_LINE_COLOR, colorLineActive, colorLineInactive);
focused = false;
}
}
@Override
public void paintSafely(Graphics g) {
super.paintSafely(g);
paintLine(g);
changeColorOnFocus(g);
}
protected void changeColorOnFocus(Graphics g) {
boolean hasFocus = focused;
JTextComponent c = getComponent();
if (c == null) {
return;
}
if (hasFocus && (activeBackground != null) && (activeForeground != null)) {
logicForChangeColorOnFocus(c, activeBackground, activeForeground);
//TODO create a new changePropriety
paintLine(c.getGraphics());
}
if (!hasFocus && (inactiveBackground != null) && (inactiveForeground != null)) {
logicForChangeColorOnFocus(c, inactiveBackground, inactiveForeground);
paintLine(c.getGraphics());
}
}