Swing events not passed to upwards to base component - java

I have a class called ComponentMover that allows you to drag around any object that's registered with it. This works if you pass it bare JPanels, but it doesn't work if the JPanel has anything inside of it, and it just stays put.
This is ComponentMover:
public class ComponentMover extends MouseAdapter {
private Insets dragInsets = new Insets(0, 0, 0, 0);
private Dimension snapSize = new Dimension(1, 1);
private Insets edgeInsets = new Insets(0, 0, 0, 0);
private boolean changeCursor = true;
private boolean autoLayout = false;
private Class<?> destinationClass;
private Component destinationComponent;
private Component destination;
private Component source;
private Point pressed;
private Point location;
private Cursor originalCursor;
private boolean autoscrolls;
private boolean potentialDrag;
private boolean shouldLock = true;
/**
* Constructor for moving individual components. The components must be
* regisetered using the registerComponent() method.
*/
public ComponentMover() {
}
/**
* Constructor to specify a Class of Component that will be moved when drag
* events are generated on a registered child component. The events will be
* passed to the first ancestor of this specified class.
*
* #param destinationClass
* the Class of the ancestor component
* #param component
* the Components to be registered for forwarding drag events to
* the ancestor Component.
*/
public ComponentMover(Class<?> destinationClass, JComponent... components) {
this.destinationClass = destinationClass;
registerComponent(components);
}
/**
* Constructor to specify a parent component that will be moved when drag
* events are generated on a registered child component.
*
* #param destinationComponent
* the component drage events should be forwareded to
* #param components
* the Components to be registered for forwarding drag events to
* the parent component to be moved
*/
public ComponentMover(JComponent destinationComponent,
JComponent... components) {
this.destinationComponent = destinationComponent;
registerComponent(components);
}
public void setLock(boolean shouldLock) {
this.shouldLock = shouldLock;
}
/**
* Get the auto layout property
*
* #return the auto layout property
*/
public boolean isAutoLayout() {
return autoLayout;
}
/**
* Set the auto layout property
*
* #param autoLayout
* when true layout will be invoked on the parent container
*/
public void setAutoLayout(boolean autoLayout) {
this.autoLayout = autoLayout;
}
/**
* Get the change cursor property
*
* #return the change cursor property
*/
public boolean isChangeCursor() {
return changeCursor;
}
/**
* Set the change cursor property
*
* #param changeCursor
* when true the cursor will be changed to the Cursor.MOVE_CURSOR
* while the mouse is pressed
*/
public void setChangeCursor(boolean changeCursor) {
this.changeCursor = changeCursor;
}
/**
* Get the drag insets
*
* #return the drag insets
*/
public Insets getDragInsets() {
return dragInsets;
}
/**
* Set the drag insets. The insets specify an area where mouseDragged events
* should be ignored and therefore the component will not be moved. This
* will prevent these events from being confused with a MouseMotionListener
* that supports component resizing.
*
* #param dragInsets
*/
public void setDragInsets(Insets dragInsets) {
this.dragInsets = dragInsets;
}
/**
* Get the bounds insets
*
* #return the bounds insets
*/
public Insets getEdgeInsets() {
return edgeInsets;
}
/**
* Set the edge insets. The insets specify how close to each edge of the
* parent component that the child component can be moved. Positive values
* means the component must be contained within the parent. Negative values
* means the component can be moved outside the parent.
*
* #param edgeInsets
*/
public void setEdgeInsets(Insets edgeInsets) {
this.edgeInsets = edgeInsets;
}
/**
* Remove listeners from the specified component
*
* #param component
* the component the listeners are removed from
*/
public void deregisterComponent(JComponent... components) {
for (JComponent component : components)
component.removeMouseListener(this);
}
/**
* Add the required listeners to the specified component
*
* #param component
* the component the listeners are added to
*/
public void registerComponent(JComponent... components) {
for (JComponent component : components){
component.addMouseListener(this);
}
}
/**
* Get the snap size
*
* #return the snap size
*/
public Dimension getSnapSize() {
return snapSize;
}
/**
* Set the snap size. Forces the component to be snapped to the closest grid
* position. Snapping will occur when the mouse is dragged half way.
*/
public void setSnapSize(Dimension snapSize) {
if (snapSize.width < 1 || snapSize.height < 1)
throw new IllegalArgumentException(
"Snap sizes must be greater than 0");
this.snapSize = snapSize;
}
/**
* Setup the variables used to control the moving of the component:
*
* source - the source component of the mouse event destination - the
* component that will ultimately be moved pressed - the Point where the
* mouse was pressed in the destination component coordinates.
*/
#Override
public void mousePressed(MouseEvent e) {
source = e.getComponent();
int width = source.getSize().width - dragInsets.left - dragInsets.right;
int height = source.getSize().height - dragInsets.top
- dragInsets.bottom;
Rectangle r = new Rectangle(dragInsets.left, dragInsets.top, width,
height);
if (r.contains(e.getPoint()))
setupForDragging(e);
}
private void setupForDragging(MouseEvent e) {
source.addMouseMotionListener(this);
potentialDrag = true;
// Determine the component that will ultimately be moved
if (destinationComponent != null) {
destination = destinationComponent;
} else if (destinationClass == null) {
destination = source;
} else // forward events to destination component
{
destination = SwingUtilities.getAncestorOfClass(destinationClass,
source);
}
pressed = e.getLocationOnScreen();
location = destination.getLocation();
if (changeCursor) {
originalCursor = source.getCursor();
source.setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
}
// Making sure autoscrolls is false will allow for smoother dragging of
// individual components
if (destination instanceof JComponent) {
JComponent jc = (JComponent) destination;
autoscrolls = jc.getAutoscrolls();
jc.setAutoscrolls(false);
}
}
/**
* Move the component to its new location. The dragged Point must be in the
* destination coordinates.
*/
#Override
public void mouseDragged(MouseEvent e) {
Point dragged = e.getLocationOnScreen();
int dragX = getDragDistance(dragged.x, pressed.x, snapSize.width);
int dragY = getDragDistance(dragged.y, pressed.y, snapSize.height);
int locationX = location.x + dragX;
int locationY = location.y + dragY;
// Mouse dragged events are not generated for every pixel the mouse
// is moved. Adjust the location to make sure we are still on a
// snap value.
if (shouldLock) {
while (locationX < edgeInsets.left)
locationX += snapSize.width;
while (locationY < edgeInsets.top)
locationY += snapSize.height;
Dimension d = getBoundingSize(destination);
while (locationX + destination.getSize().width + edgeInsets.right > d.width)
locationX -= snapSize.width;
while (locationY + destination.getSize().height + edgeInsets.bottom > d.height)
locationY -= snapSize.height;
}
// Adjustments are finished, move the component
destination.setLocation(locationX, locationY);
}
/*
* Determine how far the mouse has moved from where dragging started (Assume
* drag direction is down and right for positive drag distance)
*/
private int getDragDistance(int larger, int smaller, int snapSize) {
int halfway = snapSize / 2;
int drag = larger - smaller;
drag += (drag < 0) ? -halfway : halfway;
drag = (drag / snapSize) * snapSize;
return drag;
}
/*
* Get the bounds of the parent of the dragged component.
*/
private Dimension getBoundingSize(Component source) {
if (source instanceof Window) {
GraphicsEnvironment env = GraphicsEnvironment
.getLocalGraphicsEnvironment();
Rectangle bounds = env.getMaximumWindowBounds();
return new Dimension(bounds.width, bounds.height);
} else {
return source.getParent().getSize();
}
}
/**
* Restore the original state of the Component
*/
#Override
public void mouseReleased(MouseEvent e) {
if (!potentialDrag)
return;
source.removeMouseMotionListener(this);
potentialDrag = false;
if (changeCursor)
source.setCursor(originalCursor);
if (destination instanceof JComponent) {
((JComponent) destination).setAutoscrolls(autoscrolls);
}
// Layout the components on the parent container
if (autoLayout) {
if (destination instanceof JComponent) {
((JComponent) destination).revalidate();
} else {
destination.validate();
}
}
}
}
What should I do with this code (or the other GUI's building code) to make me able to drag and drop components with children?

You have an adaptation of a ComponentMover by #camickr. The original and your version work fine with components that have children. Perhaps the problem is elsewhere. Consider posting an MCVE that illustrates the problem.
Here is a simple demo:
import java.awt.Color;
import java.awt.Dimension;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class TestMove extends JPanel{
public TestMove() {
setLayout(null);
JPanel panel = new JPanel();
panel.add(new JLabel("label"));
panel.add(new JButton("button"));
panel.setBorder(BorderFactory.createLineBorder(Color.GREEN));
panel.setBounds(50, 50, 200, 50);
add(panel);
ComponentMover cm = new ComponentMover();
cm.registerComponent(panel);
}
public Dimension getPreferredSize() {
return new Dimension(300, 200);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationByPlatform(true);
TestMove panel = new TestMove();
frame.add(panel);
frame.pack();
frame.setVisible(true);
}
});
}
}

Related

JTable in JPanel only shows all its values when scrolling on it or by showing-hidding-showing the JPanel on runtime manually

I am working in a Java desktop game where I am trying to display some panels composed by a JTable with a JScrollPane, which has only one column and several rows, containing the data I want to display. This panels are not visible when the application starts, because they are shown depending on the JButton pressed.
When I start my application, these panels are already added to the frame, but not visible. At the moment I try to display them by pressing the corresponding button, they are shown, but not all the rows are visible. If I press the button again, the panel is hidden, and if I press again the button to display it again, now it is shown with all its rows visible.
For some reason, just by setting its visibility to true -> false -> true by pressing the corresponding button, the JTable of the panel displays all its rows, but when I display it the first time, it doesn't... I need to do it twice.
To check this, I try to set the panel visibility to true -> false -> true when the application starts programmatically, but it doesn't works. It only works if I press the button that displays the panel (remember, twice, the first time it doesn't shows all the rows, the second time it does). Also, I've checked by debugging if, at the moment I set the panel visibility to true the first time, it has all the data inside, and it is correct, so it is something just only graphic, because the data is there. Also I realized that by scrolling with the mouse the first time I show the panel, it shows all the data, so I guess it must be refreshing something when I scroll, or when I show the panel for the second time I press the corresponding button.
I've tried to revalidate() and repaint() the table, to fireTableDataChanged() and fireTableStructureChanged() the model of the table. Also I've created a thread which starts at the same time the application starts, which sets the visibility of these panels to true and false at the beginning, and revalidating the tables, just to try to see what could be happening when showing/hidding the panels.
After create this thread, I realized that if I set the visibility of this panels to true from the beginning, I see how the UI thread "refresh" the panels in some way, as I can see them uncomplete, and after complete, in a split second. But after, I have to close them manually, because I cannot control (I tried) the time needed to see them filled before close them.
Here is a picture of the panel when I setVisible(true) one of these panels:
And here is the picture of the same panel when I hide and show it again (manually), without perform any other actions:
Here is the code of the table model set in the JTable of the panel:
/**
* Class to create the model instance for the selector panel list
*/
public class CustomTableModelForPredefinedMessagesSelectorKeyboard extends DefaultTableModel {
private ArrayList selectedList = new ArrayList<>();
public CustomTableModelForPredefinedMessagesSelectorKeyboard() {
this.addColumn(LanguageConfiguration.getLanguageSelected().getString("selection"));
//setListType(ListType.PREDEFINED_MESSAGES);
setListType();
}
/**
* Function to get the size of the list
*
* #return the list size
*/
//#Override
public int getSize() {
return selectedList.size();
}
/**
* Function to get the element of a specific index from the list
*
* #param index index of the message to be retrieved
* #return the message text of the corresponding index
*/
public Object getElementAt(int index) {
return selectedList.get(index).toString();
}
public ArrayList getSelectedList() {
return selectedList;
}
public void setSelectedList(ArrayList selectedList) {
this.selectedList = selectedList;
}
/**
* Function to set the list of the selector panel according to the list type selected
*/
#SuppressWarnings("unchecked")
public void setListType() {
selectedList.add("selectorPanel_PredefMsg_EnemyOnSight");
selectedList.add("selectorPanel_PredefMsg_GreenAlert");
selectedList.add("selectorPanel_PredefMsg_HowAreYou");
selectedList.add("selectorPanel_PredefMsg_InminentAttack");
selectedList.add("selectorPanel_PredefMsg_No");
selectedList.add("selectorPanel_PredefMsg_Positioned");
selectedList.add("selectorPanel_PredefMsg_Ready");
selectedList.add("selectorPanel_PredefMsg_RedAlert");
selectedList.add("selectorPanel_PredefMsg_ReturnToBase");
selectedList.add("selectorPanel_PredefMsg_TargetOutOfReach");
selectedList.add("selectorPanel_PredefMsg_WaitingOrders");
selectedList.add("selectorPanel_PredefMsg_WeHaveAProblem");
selectedList.add("selectorPanel_PredefMsg_YellowAlert");
selectedList.add("selectorPanel_PredefMsg_Yes");
for (Object string : selectedList)
this.addRow(new Object[]{LanguageConfiguration.getLanguageSelected().getString((String) string)});
if (SwingInterfaceSubJPanels.getPredefinedMessagesSelectorJPanel() != null)
for (Component component : SwingInterfaceSubJPanels.getPredefinedMessagesSelectorJPanel().getComponents())
if (component instanceof JScrollPane) {
JScrollPane messagesListScrollPane = (JScrollPane) component;
JViewport viewport = messagesListScrollPane.getViewport();
preselectFirstElement((CustomJTable) viewport.getView());
break;
}
}
/**
* Function to pre-select the firs item of the list in the selector list
*
* #param customJTable the table where the selection will be performed
*/
private void preselectFirstElement(CustomJTable customJTable) {
if (customJTable.getRowCount() > 0)
customJTable.getSelectionModel().setSelectionInterval(0, 0);
}
}
And here is the code of the panel:
/**
* Class to create and manage a selector keyboard
*/
public class PredefinedMessagesSelectorKeyboard extends JPanel {
/**
* Color of shadow
*/
private final Color shadowColor;
/**
* Double values for Horizontal and Vertical radius of corner arcs
*/
private final Dimension arcs;
/**
* Variables to get the coordinates of the mouse on mouse click event over the jpanel
*/
private int xJPanelCoord, yJPanelCoord;
Component componentToManage;
SelectorConfirmationController.Type selectorPanelType;
/**
* Constructor to create the selector panel structure and add its components
*/
public PredefinedMessagesSelectorKeyboard() {
DisplayMode displayMode = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDisplayMode();
double screenWidth = displayMode.getWidth();
double screenHeight = displayMode.getHeight();
this.setPreferredSize(new Dimension((int) Math.round(screenWidth * 0.35), (int) Math.round(screenHeight * 0.6)));
//this.setBackground(new java.awt.Color(5, 122, 122));
this.setBackground(new Color(150, 150, 150));
addSelectorPanelComponents();
setVisible(false);
setOpaque(false);
makeJPanelDraggable();
shadowColor = Color.black;
arcs = new Dimension(100, 100);
}
/**
* Function to add the components of the JPanel
*/
private void addSelectorPanelComponents() {
this.setLayout(new GridBagLayout());
addSelectorPanelJTable();
addSelectorPanelButtons();
addSelectorPanelCloseJButton();
}
/**
* Function to add the panel with the elements available for selection
*/
private void addSelectorPanelJTable() {
GridBagConstraints gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 0;
gridBagConstraints.gridwidth = 4;
gridBagConstraints.gridheight = 2;
gridBagConstraints.weighty = 1.0;
gridBagConstraints.fill = GridBagConstraints.BOTH;
gridBagConstraints.insets = new Insets(40, 20, 20, 0);
CustomTableModelForPredefinedMessagesSelectorKeyboard customTableModelForPredefinedMessagesSelectorPanelList = new CustomTableModelForPredefinedMessagesSelectorKeyboard();
CustomJTable predefinedMessagesselectorPanelJTable = new CustomJTable(customTableModelForPredefinedMessagesSelectorPanelList);
predefinedMessagesselectorPanelJTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
predefinedMessagesselectorPanelJTable.setName("predefinedMessagesSelectorPanelJTable");
JScrollPane selectorJTableJScrollPane = new JScrollPane(predefinedMessagesselectorPanelJTable);
selectorJTableJScrollPane.getViewport().setBackground(new Color(24, 27, 34));
add(selectorJTableJScrollPane, gridBagConstraints);
}
/**
* Function to add the close panel button and the selection confirmation button
*/
private void addSelectorPanelButtons() {
GridBagConstraints gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridx = 4;
gridBagConstraints.gridy = 1;
gridBagConstraints.insets = new Insets(20, 20, 0, 20);
JButton selectPreviousButton = createScaledSwingShapedButton("/images/boton_popup_panel_selector_anterior.png",
"/images/boton_popup_panel_selector_anterior_seleccionado.png");
selectPreviousButton.setName("selectorPanelPreviousButton");
selectPreviousButton.setToolTipText(LanguageConfiguration.getLanguageSelected().getString("tooltipTextPreviousButton"));
selectPreviousButton.addActionListener(e -> {
for (Component component : getComponents())
if (component instanceof JScrollPane) {
JScrollPane messagesListScrollPane = (JScrollPane) component;
JViewport viewport = messagesListScrollPane.getViewport();
selectPrevious((CustomJTable) viewport.getView());
break;
}
});
JButton confirmSelectedButton = createScaledSwingShapedButton("/images/boton_popup_panel_selector_confirmar.png",
"/images/boton_popup_panel_selector_confirmar_seleccionado.png");
confirmSelectedButton.setName("selectorPanelConfirmButton");
confirmSelectedButton.setToolTipText(LanguageConfiguration.getLanguageSelected().getString("tooltipTextConfirmButton"));
confirmSelectedButton.addActionListener(new SelectorConfirmationController(componentToManage, selectorPanelType));
JButton selectNextButton = createScaledSwingShapedButton("/images/boton_popup_panel_selector_siguiente.png",
"/images/boton_popup_panel_selector_siguiente_seleccionado.png");
selectNextButton.setName("selectorPanelNextButton");
selectNextButton.setToolTipText(LanguageConfiguration.getLanguageSelected().getString("tooltipTextNextButton"));
selectNextButton.addActionListener(e -> {
for (Component component : getComponents()){
if (component instanceof JScrollPane){
JScrollPane messagesListScrollPane = (JScrollPane) component;
JViewport viewport = messagesListScrollPane.getViewport();
selectNext((CustomJTable) viewport.getView());
break;
}
}
});
JPanel lateralButtonsPanel = new JPanel();
lateralButtonsPanel.setLayout(new BoxLayout(lateralButtonsPanel, BoxLayout.Y_AXIS));
lateralButtonsPanel.setOpaque(false);
lateralButtonsPanel.setName("lateralButtonsPanel");
lateralButtonsPanel.add(selectPreviousButton);
lateralButtonsPanel.add(confirmSelectedButton);
lateralButtonsPanel.add(selectNextButton);
add(lateralButtonsPanel, gridBagConstraints);
}
/**
* Function to create and add the close panel button to the panel
*/
private void addSelectorPanelCloseJButton() {
GridBagConstraints gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridx = 4;
gridBagConstraints.gridy = 0;
//gridBagConstraints.anchor = GridBagConstraints.NORTHEAST;
gridBagConstraints.insets = new Insets(20, 20, 0, 20);
JButton closeMessagesConsoleButton = createScaledSwingShapedButton("/images/boton_consola_mensajes_2.png",
"/images/boton_consola_mensajes_2_seleccionado.png");
closeMessagesConsoleButton.setName("selectorPanelCloseButton");
closeMessagesConsoleButton.setToolTipText(LanguageConfiguration.getLanguageSelected().getString("tooltipTextClosePanelButton"));
//closeMessagesConsoleButton.addActionListener(e -> setVisible(false));
closeMessagesConsoleButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
/*if (getComponentToManage().getName().equals("messageBoxTable"))*/
SwingInterfaceSubJPanels.getMainScreenUpperInformationLabel().setVisible(false);
setVisible(false);
}
});
add(closeMessagesConsoleButton, gridBagConstraints);
}
/**
* Function to select the next item of the list in the selector list
* #param customJTable the table where the selection will be performed
*/
private void selectPrevious(CustomJTable customJTable){
if (customJTable.getSelectedRow() > 0) {
customJTable.getSelectionModel().setSelectionInterval(customJTable.getSelectedRow() - 1, customJTable.getSelectedRow() - 1);
customJTable.scrollRectToVisible(new Rectangle(customJTable.getCellRect(customJTable.getSelectedRow()-1, 0, true)));
}
}
/**
* Function to select the next item of the list in the selector list
* #param customJTable the table where the selection will be performed
*/
private void selectNext(CustomJTable customJTable){
if (customJTable.getSelectedRow() >= 0 && customJTable.getSelectedRow() < customJTable.getRowCount()-1) {
customJTable.getSelectionModel().setSelectionInterval(customJTable.getSelectedRow() + 1, customJTable.getSelectedRow() + 1);
customJTable.scrollRectToVisible(new Rectangle(customJTable.getCellRect(customJTable.getSelectedRow()+1, 0, true)));
}
}
public Component getComponentToManage() {
return componentToManage;
}
public void setComponentToManage(Component componentToManage) {
this.componentToManage = componentToManage;
}
public SelectorConfirmationController.Type getSelectorPanelType() {
return selectorPanelType;
}
public void setSelectorPanelType(SelectorConfirmationController.Type selectorPanelType) {
this.selectorPanelType = selectorPanelType;
}
/**
* Function to create and return a scaled swing shaped button with its corresponding images
*
* #param buttonImage button image when the button is not pressed
* #param buttonPressedImage button image when the button is pressed
* #return the button already built
*/
private JButton createScaledSwingShapedButton(String buttonImage, String buttonPressedImage) {
Image scaledImage;
try {
SwingShapedButton swingShapedButton = new SwingShapedButton();
JButton newButton = (JButton) swingShapedButton.createComponent(SwingShapedButton.ButtonShape.ROUND);
Image imageButton = ImageIO.read(getClass().getResource(buttonImage));
scaledImage = scaleImage(imageButton);
newButton.setIcon(new ImageIcon(scaledImage));
Image imageButtonPressed = ImageIO.read(getClass().getResource(buttonPressedImage));
scaledImage = scaleImage(imageButtonPressed);
newButton.setPressedIcon(new ImageIcon(scaledImage));
return newButton;
} catch (IllegalArgumentException | IOException e) {
e.printStackTrace();
DataBase.database.insertSystemErrorLog(Thread.currentThread().getStackTrace()[1].getMethodName(), e);
return (JButton) new SwingShapedButton().createComponent(SwingShapedButton.ButtonShape.ROUND);
}
}
/**
* Function to scale the images of the buttons according to the screen resolution
*
* #param imageButton the image to be set to the button
* #return the image resized
*/
private Image scaleImage(Image imageButton) {
return imageButton.getScaledInstance((int) Math.round(((BufferedImage) imageButton).getWidth() * InterfaceControlsManager.getWidth_percentage()),
(int) Math.round(((BufferedImage) imageButton).getHeight() * InterfaceControlsManager.getHeight_percentage()),
Image.SCALE_SMOOTH);
}
/**
* Function to allow the panel to be draggable over the frame
*/
private void makeJPanelDraggable() {
this.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
xJPanelCoord = e.getX();
yJPanelCoord = e.getY();
}
});
this.addMouseMotionListener(new MouseMotionAdapter() {
#Override
public void mouseDragged(MouseEvent e) {
int x = e.getXOnScreen() - xJPanelCoord;
int y = e.getYOnScreen() - yJPanelCoord;
setLocation(x, y);
}
});
}
/**
* Function to set the appearance of the panel
*
* #param g the graphics to be set
*/
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int width = getWidth();
int height = getHeight();
/*
Distance between shadow border and opaque panel border
*/
int shadowGap = 5;
int shadowAlpha = 10;
Color shadowColorA = new Color(shadowColor.getRed(),
shadowColor.getGreen(), shadowColor.getBlue(), shadowAlpha);
Graphics2D graphics = (Graphics2D) g;
//Sets antialiasing if HQ.
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
//Draws shadow borders if any.
int strokeSize = 1;
boolean shady = true;
graphics.setColor(shadowColorA);
int shadowOffset = 4;
graphics.fillRoundRect(
shadowOffset,// X position
shadowOffset,// Y position
width - strokeSize - shadowOffset, // width
height - strokeSize - shadowOffset, // height
arcs.width, arcs.height);// arc Dimension
//Draws the rounded opaque panel with borders.
graphics.setColor(getBackground());
graphics.fillRoundRect(0, 0, width - shadowGap,
height - shadowGap, arcs.width, arcs.height);
graphics.setColor(getForeground());
graphics.setStroke(new BasicStroke(strokeSize));
graphics.drawRoundRect(0, 0, width - shadowGap,
height - shadowGap, arcs.width, arcs.height);
//Sets strokes to default, is better.
graphics.setStroke(new BasicStroke());
}
}
Can someone explain to me why I see this effect in the panel? There is some reason why the JTable doesn't show its data the first time I setVisible(true) the panel, but it is displayed properly the second time? Could be something with the UI, or maybe I am not realizing about something here?
Thanks for any comment you can give me!

Swing UI: not visible components remain active

I'm building a user interface using JComponents.
The UI should work in this way: depending on the value set (e.g. through a JComboBox), different JComponents are displayed.
My though was to #Override the isVisible() method of each component or, alternatively, to set them visible or not through the JComboBox. Indeed, both the two methods works, in the sense that the desired components appear and disappear from JPanel when I change the JComboBox value.
The problem is that, even if a component is not visible inside the panel, it is still active and clicking on the position in which it should be (if visible), it triggers its action. E.g. I move the mouse over the position in which another JComboBox should be; the combobox is not visible, but mouse cursor turns into Cursor.HAND_CURSOR and, if I click, the popup list of combobox items appears and I'm able to select one of these items.
Here is a salmple of the code I'm using:
public class MyPanel extends JPanel{
public MyPanel(){
super(new GridBagLayout());
GridBagConstraints g = new GridBagConstraints(
0, // int gridx
-1, // int gridy
1, // int gridwidth
1, // int gridheight
1, // double weightx
1, // double weighty
GridBagConstraints.NORTHWEST, // int anchor
GridBagConstraints.NONE, // int fill
new Insets(0,0,0,0), // Insets insets
0, // int ipadx
0 // int ipady
);
String[] comboItems = {"ShowCombo1","ShowCheckbox","ShowTextField"};
JComboBox combo = new JComboBox(comboItems);
JComboBox combo1 = new JComboBox(){
#Override
public boolean isVisible(){
return combo.getSelectedIndex()==0;
}
};
JCheckBox checkBox= new JCheckBox(){
#Override
public boolean isVisible(){
return combo.getSelectedIndex()==1;
}
};
JTextField textField= new JTextField(){
#Override
public boolean isVisible(){
return combo.getSelectedIndex()==2;
}
};
add(combo,g);
g.gridy += 1;
add(combo1,g);
g.gridy += 1;
add(checkBox,g);
g.gridy += 1;
add(textField,g);
}
}
Is there a better way to manage these kind of user interfaces?
I think with your approach you are just return the flag to true based on the selection. Internally the setVisible(false) does more than just switching the flag off. It calls super.setVisible(false) which does the below.
/**
* Shows or hides this component depending on the value of parameter
* <code>b</code>.
* <p>
* This method changes layout-related information, and therefore,
* invalidates the component hierarchy.
*
* #param b if <code>true</code>, shows this component;
* otherwise, hides this component
* #see #isVisible
* #see #invalidate
* #since JDK1.1
*/
public void setVisible(boolean b) {
show(b);
}
/**
* #deprecated As of JDK version 1.1,
* replaced by <code>setVisible(boolean)</code>.
*/
#Deprecated
public void show() {
if (!visible) {
synchronized (getTreeLock()) {
visible = true;
mixOnShowing();
ComponentPeer peer = this.peer;
if (peer != null) {
peer.setVisible(true);
createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED,
this, parent,
HierarchyEvent.SHOWING_CHANGED,
Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));
if (peer instanceof LightweightPeer) {
repaint();
}
updateCursorImmediately();
}
if (componentListener != null ||
(eventMask & AWTEvent.COMPONENT_EVENT_MASK) != 0 ||
Toolkit.enabledOnToolkit(AWTEvent.COMPONENT_EVENT_MASK)) {
ComponentEvent e = new ComponentEvent(this,
ComponentEvent.COMPONENT_SHOWN);
Toolkit.getEventQueue().postEvent(e);
}
}
Container parent = this.parent;
if (parent != null) {
parent.invalidate();
}
}
}
Though i do not understand what they actually do :-), I feel this part of code needs to be executed.

Pan chart using mouse - Jfreechart

Can we implement the pan functionality as a mouse drag event in JfreeChart? Right now I press CTRL and drag my mouse to pan a chart. I want to implement the pan functionality just by dragging the mouse. Is that possible ?
It is apparently impossible to change the modifier key with the current JFreeChart API, as discussed here (but it is in the pipeline).
However, everything is there to pan a chart programmatically, so you could try the following:
Add a MouseMotionListener to your ChartPanel to track mouseDragged() events.
From these events, compute the requested movement of the chart.
Call directly XYPlot.panDomainAxes() and XYPlot.panRangeAxis() (API here).
Take inspiration from ChartPanel source code:
/**
* Temporary storage for the width and height of the chart
* drawing area during panning.
*/
private double panW, panH;
/** The last mouse position during panning. */
private Point panLast;
/**
* The mask for mouse events to trigger panning.
*
* #since 1.0.13
*/
private int panMask = InputEvent.CTRL_MASK;
...
/**
* Handles a 'mouse pressed' event.
* <P>
* This event is the popup trigger on Unix/Linux. For Windows, the popup
* trigger is the 'mouse released' event.
*
* #param e The mouse event.
*/
#Override
public void mousePressed(MouseEvent e) {
if (this.chart == null) {
return;
}
Plot plot = this.chart.getPlot();
int mods = e.getModifiers();
if ((mods & this.panMask) == this.panMask) {
// can we pan this plot?
if (plot instanceof Pannable) {
Pannable pannable = (Pannable) plot;
if (pannable.isDomainPannable() || pannable.isRangePannable()) {
Rectangle2D screenDataArea = getScreenDataArea(e.getX(),
e.getY());
if (screenDataArea != null && screenDataArea.contains(
e.getPoint())) {
this.panW = screenDataArea.getWidth();
this.panH = screenDataArea.getHeight();
this.panLast = e.getPoint();
setCursor(Cursor.getPredefinedCursor(
Cursor.MOVE_CURSOR));
}
}
// the actual panning occurs later in the mouseDragged()
// method
}
}
else if (this.zoomRectangle == null) {
...
}
}
...
/**
* Handles a 'mouse dragged' event.
*
* #param e the mouse event.
*/
#Override
public void mouseDragged(MouseEvent e) {
// if the popup menu has already been triggered, then ignore dragging...
if (this.popup != null && this.popup.isShowing()) {
return;
}
// handle panning if we have a start point
if (this.panLast != null) {
double dx = e.getX() - this.panLast.getX();
double dy = e.getY() - this.panLast.getY();
if (dx == 0.0 && dy == 0.0) {
return;
}
double wPercent = -dx / this.panW;
double hPercent = dy / this.panH;
boolean old = this.chart.getPlot().isNotify();
this.chart.getPlot().setNotify(false);
Pannable p = (Pannable) this.chart.getPlot();
if (p.getOrientation() == PlotOrientation.VERTICAL) {
p.panDomainAxes(wPercent, this.info.getPlotInfo(),
this.panLast);
p.panRangeAxes(hPercent, this.info.getPlotInfo(),
this.panLast);
}
else {
p.panDomainAxes(hPercent, this.info.getPlotInfo(),
this.panLast);
p.panRangeAxes(wPercent, this.info.getPlotInfo(),
this.panLast);
}
this.panLast = e.getPoint();
this.chart.getPlot().setNotify(old);
return;
}
...
}
...
/**
* Handles a 'mouse released' event. On Windows, we need to check if this
* is a popup trigger, but only if we haven't already been tracking a zoom
* rectangle.
*
* #param e information about the event.
*/
#Override
public void mouseReleased(MouseEvent e) {
// if we've been panning, we need to reset now that the mouse is
// released...
if (this.panLast != null) {
this.panLast = null;
setCursor(Cursor.getDefaultCursor());
}
...
}
EDIT: Noticing that the only problem with the current API is that panMask is private, why don't you try to hack the field with reflection:
Field mask = ChartPanel.class.getDeclaredField("panMask");
mask.setAccessible(true);
mask.set(yourChartPanel, Integer.valueOf(0)); // The "0" mask is equivalent to no mask. You could also set a different modifier.
Solution still not provided with new version so i put what works flawlessly for me, it also auto zoom range axis when you scroll:
ChartPanel panel = new ChartPanel(chart);
panel.setMouseZoomable(false);
panel.setMouseWheelEnabled(true);
panel.setDomainZoomable(true);
panel.setRangeZoomable(false);
panel.setPreferredSize(new Dimension(1680, 1100));
panel.setZoomTriggerDistance(Integer.MAX_VALUE);
panel.setFillZoomRectangle(false);
panel.setZoomOutlinePaint(new Color(0f, 0f, 0f, 0f));
panel.setZoomAroundAnchor(true);
try {
Field mask = ChartPanel.class.getDeclaredField("panMask");
mask.setAccessible(true);
mask.set(panel, 0);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
panel.addMouseWheelListener(arg0 -> panel.restoreAutoRangeBounds());
Now JFreeChart behaves like any other professional charting software.
Here is my solution.
Regards
TA
ChartPanel cp = new ChartPanel(chart)
{
/**
* A hack to change the zoom and panning function.
* With this override we can pan around by dragging.
* If SHIFT is pressed we get the zoom rectangle.
* #param e
*/
#Override
public void mousePressed(MouseEvent e)
{
int mods = e.getModifiers();
int panMask = MouseEvent.BUTTON1_MASK;
if (mods == MouseEvent.BUTTON1_MASK+MouseEvent.SHIFT_MASK)
{
panMask = 255; //The pan test will match nothing and the zoom rectangle will be activated.
}
try
{
Field mask = ChartPanel.class.getDeclaredField("panMask");
mask.setAccessible(true);
mask.set(this, panMask);
}
catch (Exception ex)
{
ex.printStackTrace();
}
super.mousePressed(e);
}
};

Jslider displaying values of array

I' m trying to change the displayed value(selected variable) to what the slider is in line with. The main issue is the worksheet I'm working from specifies this
"The displaySelected method is responsible for displaying just the selected item. Look at it,and work out why it is always element 0 that is displayed – it is something quite simple, and not something complex."
I understand that the change of display requires the variable selected, I've already tried ( g.drawString(names[selected], 200, 150);) but the issue with this is that it only does value 4 of the array and resets to 0 once moved and doesn't, I know that I have to change the value of selected then, I've tried selected = selector.getValue(); but I'm returned with a null error.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
/**
* A simple address database for Practical 5B
* Demonstrates arrays, graphics, selection.
*/
public class Addresses extends JFrame
implements ChangeListener
{
/**
* Frame coordinate constants
*/
private static final int FRAME_X = 200;
private static final int FRAME_Y = 200;
/**
* Frame size constants
*/
private static final int FRAME_WIDTH = 500;
private static final int FRAME_HEIGHT = 400;
/**
* The slider for selecting an address record (selectable 0 to size-1).
*/
private JSlider selector;
/**
* Array to hold the database.
*/
private String[] names;
/**
* To indicate which entry is currently selected.
*/
private int selected;
/**
* The drawing panel for display of information.
*/
private JPanel panel;
/**
* Drawing panel size constants
*/
private final int PANEL_WIDTH = 400;
private final int PANEL_HEIGHT = 300;
/**
* The main program launcher for the Addresses class.
*
* #param args The command line arguments (ignored here).
*/
public static void main( String[] args )
{
Addresses frame = new Addresses();
frame.setSize(FRAME_WIDTH, FRAME_HEIGHT);
frame.setUpData(); // Initial data set-up
frame.createGUI(); // Initial GUI set-up
frame.setVisible( true );
}
/**
* Sets up the graphical user interface.
*/
private void createGUI()
{
setDefaultCloseOperation( EXIT_ON_CLOSE );
Container window = getContentPane();
window.setLayout( new FlowLayout() );
// Slider for selecting an address entry
selector = new JSlider(JSlider.VERTICAL, 0, 0, 0);
// Note: the useable range of the slider is 0 - 0 at the moment!
window.add(selector);
selector.addChangeListener(this);
// Graphics panel for displaying the address list
panel = new JPanel()
{
// paintComponent is called automatically when a screen refresh is needed
public void paintComponent(Graphics g)
{
// g is a cleared panel area
super.paintComponent(g); // Paint the panel's background
paintScreen(g); // Then the required graphics
}
};
panel.setPreferredSize( new Dimension( PANEL_WIDTH, PANEL_HEIGHT ) );
panel.setBackground( Color.white );
window.add( panel );
}
/**
* Helper method to set up the array data, and the associated variable selected,
* with their initial configuration.
*/
private void setUpData()
{
// All the data is "built-in": set it up here - just one entry at the moment
names = new String[6]; // Create the array with space for one entry
names[0] = "James"; // The entry
names[1] = "Connor";
names[2] = "Alfred";
names[3] = "Billy";
names[4] = "Jack";
names[5] = "Chris";
selected = names.length-1; // Indicate that entry 0 is selected
}
/**
* This methods redraws the screen.
*/
private void paintScreen(Graphics g)
{
displayList(g);
displaySelected(g);
}
/**
* Display all the elements of array names in a column on the screen.
*/
private void displayList(Graphics g)
{
int y = 100; // Top y coordinate of the column
g.setColor(Color.black);
/*
g.drawString(names[0], 20, y);
g.drawString(names[1], 20, y+25);
g.drawString(names[2], 20, y+50);
g.drawString(names[3], 20, y+75);
g.drawString(names[4], 20, y+100);
g.drawString(names[5], 20, y+125);
*/
for (int i = 0; i< names.length; i++)
g.drawString(names[i], 20, y+25*i);
}
/**
* Display the single element of array names that is currently selected by the slider.
*/
private void displaySelected(Graphics g)
{
g.setColor(Color.black);
g.drawString("Current selection is:", 200, 135);
g.drawString(names[selected], 200, 150);
}
/**
* Reacts to adjustment of the slider.
* Notes the new selector setting, then forces screen refresh.
*/
public void stateChanged( ChangeEvent e )
{
// selector has been adjusted: record the new setting
selected = selector.getValue();
repaint(); // Refresh the screen
}
}
You never set the maximum value for the slider. That's why you can't move it. Make this change to your code, then you will be able to debug the rest of this program.
selector = new JSlider(JSlider.VERTICAL, 0, names.length-1 /* HERE */ , 0);

How can I solve different types of collection

There are a lot of questions in here.
I wrote a code this far, but hard to write in code in some methods.
1.I don't know how to do setDice(List dice) method. If I use for(JButton b:dice), then it keeps giving me compile-time error.
2.Help me to implement setWordIsCorrect(boolean isCorrect) & clearCurrentWord() methods
Make sure you cannot touch other methods and modify the method signatures.
package cse1030.games.boggle;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
/**
* The view for the Boggle app. Please see the lab for a detailed description of
* the view.
*
* #author CSE1030_F13_14
*
*/
public class BoggleView extends JFrame implements ActionListener {
/**
* The string representing the clear command. The view listens for its own
* clear event.
*/
public static final String CLEAR_COMMAND = "clear";
/**
* The string representing the roll command.
*/
public static final String ROLL_COMMAND = "roll";
/**
* The string repesenting the submit command.
*/
public static final String SUBMIT_COMMAND = "submit";
/**
* A list that contains references to the buttons representing the dice.
*/
private List<JButton> diceButtons;
/**
* The text field that displays the current word.
*/
private JTextField word;
/**
* The set of dice buttons that have already been used to form the current
* word.
*/
private Set<JButton> usedButtons;
/**
* The text area that displays the list of correct words.
*/
private JTextArea correctWords;
/**
* The text area that displays the list of incorrect words.
*/
private JTextArea incorrectWords;
/**
* Create the Boggle user interface. Please see the lab for a detailed
* description of the user interface.
*
* #param controller
* the controller that listens for submit and roll events
*/
public BoggleView(BoggleController controller) {
super("Boggle");
this.diceButtons = new ArrayList<JButton>();
this.usedButtons = new HashSet<JButton>();
JPanel contentPanel = new JPanel();
JPanel leftPanel = this.makeLeftPanel();
JPanel rightPanel = this.makeRightPanel();
JPanel middlePanel = this.makeMiddlePanel(controller);
contentPanel.add(leftPanel);
contentPanel.add(middlePanel);
contentPanel.add(rightPanel);
this.setContentPane(contentPanel);
this.pack();
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
/**
* Creates the panel that contains the buttons representing the Boggle dice.
*
* #return the <code>JPanel</code> that contains the buttons representing the
* Boggle dice.
*
*/
private JPanel makeDicePanel() {
Font font = new Font(Font.SANS_SERIF, Font.BOLD, 32);
JPanel p = new JPanel();
p.setLayout(new GridLayout(4, 4));
p.setMaximumSize(new Dimension(450, 450));
for (int i = 0; i < 16; i++) {
JButton b = new JButton("" + i);
b.setPreferredSize(new Dimension(100, 100));
b.setMaximumSize(b.getSize());
b.setFont(font);
b.setBackground(Color.WHITE);
b.setActionCommand("" + i);
b.addActionListener(this);
p.add(b);
this.diceButtons.add(b);
}
return p;
}
/**
* Returns the buttons surrounding the button representing the die that was
* last selected by the user. These are the buttons that could legally be
* chosen next by the user when forming a word.
*
* #param idx
* the index of the button representing the die that was last
* selected by the user
* #return the buttons surrounding the last selected die
*/
private List<JButton> findNeighbors(int idx) {
List<JButton> neighbors = new ArrayList<JButton>();
final int row = idx / 4;
final int col = idx % 4;
final int minRow = Math.max(0, row - 1);
final int maxRow = Math.min(3, row + 1);
final int minCol = Math.max(0, col - 1);
final int maxCol = Math.min(3, col + 1);
for (int i = minRow; i <= maxRow; i++) {
for (int j = minCol; j <= maxCol; j++) {
int n = i * 4 + j;
if (n != idx) {
neighbors.add(this.diceButtons.get(n));
}
}
}
return neighbors;
}
/**
* Disable all of the buttons representing the dice.
*/
private void disableAllDiceButtons() {
for (JButton b : this.diceButtons) {
b.setEnabled(false);
}
}
/**
* Enable all of the buttons representing the dice.
*/
private void enableAllDiceButtons() {
for (JButton b : this.diceButtons) {
b.setEnabled(true);
b.setBackground(Color.WHITE);
}
}
/**
* Responds to events from the view. This method responds to an event where
* the action command is either <code>BoggleView.CLEAR_COMMAND</code>,
* <code>BoggleView.ROLL_COMMAND</code>, or
* <code>BoggleView.SUBMIT_COMMAND</code>.
*
* #param event
* an event emitted by the view
*
* #see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
*/
#Override
public void actionPerformed(ActionEvent event) {
String command = event.getActionCommand();
if (command.equals(CLEAR_COMMAND)) {
this.clearCurrentWord();
} else if (command.equals(ROLL_COMMAND)) {
this.clearCorrectWords();
this.clearIncorrectWords();
this.clearCurrentWord();
} else {
try {
int d = Integer.parseInt(command);
JButton b = this.diceButtons.get(d);
b.setBackground(Color.BLUE);
this.word.setText(this.word.getText() + b.getText());
this.usedButtons.add(b);
this.disableAllDiceButtons();
List<JButton> neighbors = findNeighbors(d);
for (JButton n : neighbors) {
if (!this.usedButtons.contains(n)) {
n.setEnabled(true);
}
}
} catch (NumberFormatException ex) {
}
}
}
/**
* Creates the left-hand panel. Please see the lab for a detailed description
* of the panel's contents.
*
* #return the left-hand <code>JPanel</code> with all of its necessary
* components
*/
private JPanel makeLeftPanel() {
// create the panel
JPanel p = new JPanel();
// set the layout for the panel to use a BoxLayout;
// BoxLayout stacks its components vertically or horizontally
p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));
// create a label for the list of correct words and add it to the panel
JLabel label = new JLabel("Correct Words");
p.add(label);
// create the list of correct words, remove the ability for the user to
// edit the list, and add it to the panel
this.correctWords = new JTextArea(30, 16);
this.correctWords.setEditable(false);
p.add(this.correctWords);
return p;
}
/**
* Creates the right-hand panel. Please see the lab for a detailed description
* of the panel's contents.
*
* #return the right-hand <code>JPanel</code> with all of its necessary
* components
*/
private JPanel makeRightPanel() {
JPanel p = new JPanel();
p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));
JLabel label = new JLabel("Incorrect Words");
p.add(label);
this.incorrectWords = new JTextArea(30, 16);
this.incorrectWords.setEditable(false);
p.add(this.incorrectWords);
return p;
}
/**
* Creates the middle panel. Please see the lab for a detailed description of
* the panel's contents.
*
* #return the middle <code>JPanel</code> with all of its necessary components
*/
private JPanel makeMiddlePanel(BoggleController controller) {
JPanel p = new JPanel();
// 1. set the layout to a BoxLayout (same as makeLeftPanel)
p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));
// 2. make the dice panel and add it to p; there is a method that makes the
// dice panel for you!
p.add(makeDicePanel());
// 3. make the contorl panel and add it to p; there is a method that makes
// the control for you!
p.add(makeControlPanel(controller));
return p;
}
/**
* Creates the panel that contains the clear, submit, and re-roll buttons, and
* the text field for the word.
*
* #return the <code>JPanel</code> that contains the controls below the dice
*
*/
private JPanel makeControlPanel(BoggleController controller) {
JPanel p = new JPanel();
// You don't need to create a lay out. JPanel uses FlowLayout if you don't
// specify a lay out.
// Make the clear button
JButton clear = new JButton("Clear");
// Set its action command to the clear command
clear.setActionCommand(BoggleView.CLEAR_COMMAND);
// Add this as an action listener; see the actionPerformed method above.
// The controller does not need to listen to this button because the model
// is not needed to clear the current word.
clear.addActionListener(this);
// Add the clear button to the panel.
p.add(clear);
// Make a text field that can display a 16 character word
this.word = new JTextField(16);
// Disable editing by the user.
this.word.setEditable(false);
// Add the text field to the panel.
p.add(this.word);
// - make the submit button
JButton submit = new JButton("Submit");
// - set its action command
submit.setActionCommand(BoggleView.SUBMIT_COMMAND);
// - add the controller as an action listener
submit.addActionListener(controller);
// - add the submit button to the panel
p.add(submit);
// - make the re-roll button
JButton roll = new JButton("Re-roll");
// - set its action command
roll.setActionCommand(BoggleView.ROLL_COMMAND);
// - add the controller as an action listener
roll.addActionListener(controller);
// - add this as an action listener
roll.addActionListener(this);
// - add the re-roll button to the panel
p.add(roll);
return p;
}
/**
* Get the current string that is in the word text field.
*
* #return the current string that is in the word text field
*/
public String getWord() {
// change the return statement below
return this.word.getText();
}
/**
* Sets the text on the buttons representing the dice.
*
* #pre. <code>dice.size() == 16</code>
*
* #param dice
* a list of 16 Boggle dice
*/
public void setDice(List<BoggleDie> dice) {
**for (JButton b : dice) {
b.setText(b.getText());
}**
}
/**
* Causes the view to update after the submitted word is evaluated for
* correctness. If <code>isCorrect == true</code> then the current word is
* added to the list of correct words. If <code>isCorrect == false</code> then
* the current word is added to the list of incorrect words. In both cases,
* the current word is cleared.
*
* #param isCorrect
* <code>true</code> if the current word has been determined to be a
* legal Boggle word, <code>false</code> otherwise
*/
public void setWordIsCorrect(boolean isCorrect) {
if(isCorrect == true) {
} else {
}
}
/**
* Clears the list of correct words.
*/
private void clearCorrectWords() {
this.correctWords.setText(null);
}
/**
* Clears the list of incorrect words.
*/
private void clearIncorrectWords() {
this.incorrectWords.setText(null);
}
/**
* Clears the current word and prepares the view to accept a new word. This
* requires re-enabling all of the dice buttons and clearing the set
* this.usedButtons
*/
private void clearCurrentWord() {
// 1. enable all of the dice buttons; there is a method that does this for
// you
enableAllDiceButtons();
// 2. set the text of this.word to the empty string
// 3. remove all of the buttons from this.usedButtons
}
public static void main(String[] args) {
BoggleView v = new BoggleView(null);
v.setVisible(true);
}
}
I will appreciate you if you can help me how to do these methods...
You need to use for (BoggleDie b : dice) or (List<JButton> dice). If the list contains BoggleDie, you must use the former.
You may want to have a list of JButtons instead
public void setDice(List<JButton> dice) {
for (JButton b : dice) {
b.setText(b.getText());
}
}
You need to make sure you actually initialize the list and add JButtons to the list before you can do anything with it.
List<JButton> diceButtons = new List<JButton>();
for (int i = 0; i < 16; i++){
diceButton.add(new JButton("" + i + 1);
}
Try this for your method
public void setDice(){
for (int i = 0; i < 16; i++){
diceButtons.add(new JButton("SomeText");
}
}
Edit: with BoggleDie class
public class BoggleDie{
int value;
public BoggleDie(int value){
this.value = value;
}
}
public class BoggleView ... {
...
private List<BoggleDie> dice = new List<BoggleDie>();
private List<JButton> diceButton = new ArrayList<JButton>();
public BoggleView(){
for (int i = 0; i < 16; i++){
dice.add(new BoggleDie(i)); // or whatever value you want for the die
}
setDice(dice);
}
public void setDice(List<BoggleDie> dice) {
for (BoggleDie b : dice) {
diceButtons.add(new JButton(b.value));
}
}
}
Change the code as follows
public void setDice(List<JButton> dice) {
for (JButton b : dice) {
b.setText(b.getText());
}
}

Categories