我在课程中没有遇到任何问题,但这让我很头疼!我的问题很简单,我不能提亮或改变我的jpanels的颜色。我觉得在我的扩展jpanel类如何与重写的paint组件以及其他类交互方面,我缺少了一些关键的东西。任务很简单,当点击一个jpanel时,它的颜色应该会变亮,而其他两种颜色会变暗。
Run down:我扩展了Jframe并添加了3个面板。我为每个面板添加了一个鼠标侦听器。当按下每一个时,鼠标侦听器都会"打印已确认的语句"。但是,它不会更改对象的颜色。我想通过在TrafficLight类中包含我的鼠标适配器,我可以更改颜色并调用重新绘制。我已经用我能想到的所有方式与之合作了,我的组织错了吗?
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
class TrafficLight3 extends JFrame {
//class variables
public JPanel red;
public JPanel yellow;
public JPanel green;
public Color r;
public Color y;
public Color gr;
public static void main ( String [] args ) {
TrafficLight3 tl = new TrafficLight3 ( );
}
// Constructor
public TrafficLight3( ) {
setTitle( "Traffic Light" );
setLayout ( new GridLayout ( 3, 1 ) );
setDefaultCloseOperation ( JFrame.EXIT_ON_CLOSE );
r = Color.RED;
red = new StopLightPanel( 100, r );
red.setPreferredSize( new Dimension ( 120, 120 ) );
red.addMouseListener ( new MouseClicked( ) );
add( red );
y = Color.YELLOW;
yellow = new StopLightPanel( 100, y );
yellow.setPreferredSize( new Dimension ( 120, 120 ) );
yellow.addMouseListener ( new MouseClicked( ) );
add( yellow );
gr = Color.GREEN;
green = new StopLightPanel( 100, gr );
green.addMouseListener ( new MouseClicked( ) );
green.setPreferredSize( new Dimension ( 120, 120 ) );
add ( green );
pack();
setLocationRelativeTo(null);
setVisible( true );
}
class MouseClicked extends MouseAdapter {
@Override
public void mouseClicked ( MouseEvent me ) {
if (me.getSource().equals( red ) ) {
r = r.brighter();
y = y.darker();
gr = gr.darker();
repaint();
}
if (me.getSource().equals( yellow )) {
r = r.darker();
y = y.brighter();
gr = gr.darker();
repaint();
}
if (me.getSource().equals( red )) {
r = r.darker();
y = y.darker();
gr = gr.brighter();
repaint();
}
}
}
class StopLightPanel extends JPanel {
private int diameter;
public Color color;
public StopLightPanel ( int d, Color c) {
diameter = d;
color = c;
}
public void paintComponent ( Graphics g ) {
super.paintComponent( g );
g.setColor ( color );
g.fillOval ( 10, 10, diameter, diameter );
}
}
}
您在一个位置更改变量的值,并期望一个完全不同的变量,即JPanel拥有的变量,同时更改,但变量不是这样工作的。
相反,我会给我的刹车灯面板一个方法,比如public void setLightOn(boolean lightOn)
,并在MouseListener中调用这个方法。该方法将改变JPanel的颜色并重新绘制
例如:
class StopLightPanel extends JPanel {
private int diameter;
private Color onColor;
private Color offColor;
private boolean lightOn;
public boolean isLightOn() {
return lightOn;
}
public void setLightOn(boolean lightOn) {
this.lightOn = lightOn;
repaint();
}
public StopLightPanel(int d, Color c) {
diameter = d;
onColor = c.brighter();
offColor = c.darker().darker();
lightOn = false;
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Color color = lightOn ? onColor : offColor;
g.setColor(color);
g.fillOval(10, 10, diameter, diameter);
}
}
例如,
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
@SuppressWarnings("serial")
class TrafficLight3 extends JFrame {
private static final int DIAMETER = 100;
private static final Color[] COLORS = { Color.red, Color.yellow, Color.green };
private StopLightPanel[] lightPanels = new StopLightPanel[COLORS.length];
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new TrafficLight3();
}
});
}
public TrafficLight3() {
setTitle("Traffic Light");
setLayout(new GridLayout(3, 1));
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
MouseAdapter mouseClicked = new MouseClicked();
for (int i = 0; i < COLORS.length; i++) {
lightPanels[i] = new StopLightPanel(DIAMETER, COLORS[i]);
lightPanels[i].addMouseListener(mouseClicked);
add(lightPanels[i]);
}
pack();
setLocationRelativeTo(null);
setVisible(true);
}
class MouseClicked extends MouseAdapter {
// better overriding mousePressed not mouseClicked
@Override
public void mousePressed(MouseEvent me) {
// set all lights dark
for (StopLightPanel lightPanel : lightPanels) {
lightPanel.setLightOn(false);
}
// turn only selected light on.
((StopLightPanel) me.getSource()).setLightOn(true);
}
}
class StopLightPanel extends JPanel {
// avoid "magic" numbers
private static final int GAP = 10;
private int diameter;
private Color onColor;
private Color offColor;
private boolean lightOn;
public boolean isLightOn() {
return lightOn;
}
public void setLightOn(boolean lightOn) {
this.lightOn = lightOn;
repaint();
}
public StopLightPanel(int diameter, Color color) {
this.diameter = diameter;
this.onColor = color.brighter();
this.offColor = color.darker().darker();
this.lightOn = false;
}
@Override
public Dimension getPreferredSize() {
int prefW = diameter + 2 * GAP;
int prefH = prefW;
return new Dimension(prefW, prefH);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
// smooth out the edge of our circle
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
Color color = lightOn ? onColor : offColor;
g2.setColor(color);
g2.fillOval(GAP, GAP, diameter, diameter);
}
}
}
有点像MCV。缺少接口
import java.awt.*;
import javax.swing.*;
import javax.swing.event.SwingPropertyChangeSupport;
import java.awt.event.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.EnumMap;
import java.util.Map;
@SuppressWarnings("serial")
class TrafficLight3 {
private static final int DIAMETER = 100;
private static void createAndShowGui() {
StopLightModel model = new StopLightModel();
StopLightView view = new StopLightView(DIAMETER);
new StopLightControl(view, model);
JFrame frame = new JFrame("Traffic Light");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(view.getMainPanel());
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
enum MyColor {
RED(Color.red, "Red"),
YELLOW(Color.yellow, "Yellow"),
GREEN(Color.green, "Green");
public Color getColor() {
return color;
}
public String getName() {
return name;
}
private MyColor(Color color, String name) {
this.color = color;
this.name = name;
}
private Color color;
private String name;
}
class StopLightModel {
public static final String SELECTED_COLOR = "selected color";
private SwingPropertyChangeSupport pcSupport = new SwingPropertyChangeSupport(this);
private MyColor selectedColor = null;
public void addPropertyChangeListener(PropertyChangeListener listener) {
pcSupport.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
pcSupport.removePropertyChangeListener(listener);
}
public MyColor getSelectedColor() {
return selectedColor;
}
public void setSelectedColor(MyColor selectedColor) {
MyColor oldValue = this.selectedColor;
MyColor newValue = selectedColor;
this.selectedColor = selectedColor;
pcSupport.firePropertyChange(SELECTED_COLOR, oldValue, newValue);
}
}
class StopLightControl {
private StopLightView view;
private StopLightModel model;
public StopLightControl(final StopLightView view, final StopLightModel model) {
this.view = view;
this.model = model;
view.setStopLightControl(this);
model.addPropertyChangeListener(new ModelListener());
}
public void setSelectedColor(MyColor myColor) {
model.setSelectedColor(myColor);
}
private class ModelListener implements PropertyChangeListener {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (StopLightModel.SELECTED_COLOR.equals(evt.getPropertyName())) {
MyColor myColor = model.getSelectedColor();
view.setSelectedColor(myColor);
}
}
}
}
class StopLightView {
private JPanel mainPanel = new JPanel(new GridLayout(0, 1));
private StopLightControl control;
private Map<MyColor, StopLightPanel> colorPanelMap = new EnumMap<>(MyColor.class);
public StopLightView(int diameter) {
MouseAdapter mouseClicked = new MouseClicked();
for (MyColor myColor : MyColor.values()) {
StopLightPanel lightPanel = new StopLightPanel(diameter, myColor);
lightPanel.addMouseListener(mouseClicked);
mainPanel.add(lightPanel);
colorPanelMap.put(myColor, lightPanel);
}
}
public void setSelectedColor(MyColor myColor) {
for (MyColor color : MyColor.values()) {
colorPanelMap.get(color).setLightOn(color == myColor);
}
}
public JComponent getMainPanel() {
return mainPanel;
}
public void setStopLightControl(StopLightControl control) {
this.control = control;
}
private class MouseClicked extends MouseAdapter {
@Override
public void mousePressed(MouseEvent mEvt) {
if (control == null) {
return;
}
StopLightPanel panel = (StopLightPanel) mEvt.getSource();
control.setSelectedColor(panel.getMyColor());
}
}
}
@SuppressWarnings("serial")
class StopLightPanel extends JPanel {
// avoid "magic" numbers
private static final int GAP = 10;
private int diameter;
private MyColor myColor;
private Color onColor;
private Color offColor;
private boolean lightOn;
public boolean isLightOn() {
return lightOn;
}
public void setLightOn(boolean lightOn) {
this.lightOn = lightOn;
repaint();
}
public StopLightPanel(int diameter, MyColor myColor) {
this.diameter = diameter;
this.myColor = myColor;
this.onColor = myColor.getColor().brighter();
this.offColor = myColor.getColor().darker().darker();
this.lightOn = false;
}
public MyColor getMyColor() {
return myColor;
}
@Override
public Dimension getPreferredSize() {
int prefW = diameter + 2 * GAP;
int prefH = prefW;
return new Dimension(prefW, prefH);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
// smooth out the edge of our circle
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
Color color = lightOn ? onColor : offColor;
g2.setColor(color);
g2.fillOval(GAP, GAP, diameter, diameter);
}
}
在actionListener
中更改的颜色与面板用于绘制自身的颜色之间没有关系。
看看JavaDocs,你会注意到
较暗/较亮
返回:
创建一个较暗/较亮版本的新Color
该CCD_ 4。
darker
/brighter
不会更改Color
对象本身,而是创建一个新的Color
对象,它是darker
/brighter
,而不是您使用的颜色
当actionListener
触发时,您可能应该为每个面板设置所需的颜色。
更好的是,您应该使用某种模型,更改模型会通知面板的每个实例,然后它会通过更新自己来响应。。。