I`m planning to use a panel as a view controler container.
//variables
CustomerSearch cs;
CardLayout cl;
string BUTTONPANEL="Page1";
Setup of variables
private void InitViews(){
cl = new CardLayout();
cs = new CustomerSearch();
cl.addLayoutComponent(cs, BUTTONPANEL);
ViewPanel.setLayout(cl);
//cl.show(ViewPanel, BUTTONPANEL);
}
the button click for updating the view:
private void SearchBtnActionPerformed(java.awt.event.ActionEvent evt) {
cl.show(ViewPanel, BUTTONPANEL);
cs.repaint();
ViewPanel.repaint();
}
But when the event is fired, nothing happens?
Can anyone tell me what I'm doing wrong?
Normally you do not add the components to the layout. They are added to the parent component, the one using the layout:
private void initViews() {
cl = new CardLayout();
viewPanel.setLayout(cl);
cs = new CustomerSearch();
viewPanel.add(cs, BUTTONPANEL);
}
This tutorial should help: How to Use CardLayout
It also is convention that variables, fields and methods are named starting with a lowercase. Classes and Interfaces start with uppercase.
EDIT
repaint is not needed in this case, the following listener should do:
private void SearchBtnActionPerformed(java.awt.event.ActionEvent evt) {
cl.show(viewPanel, BUTTONPANEL);
}
Related
The Buttons in my JPanel don't show up when it's loaded, only when I resize the window or move my mouse over it. In other discussions the use of "validate()" or "repaint()" was suggested, but that doesn't work for me.
I'm using a basic model view controller design and I am pretty sure that I'm doing everything else correctly.
Just in case you wonder, of course more panels will be added to the frame, that's the purpose of the update() and changeCards() methods.
Here's my frame:
public class View extends JFrame {
private MainMenuPanel mainMenu;
private final String MAIN_MENU_CONSTRAINTS = "MAIN_MENU";
public View() {
super();
init();
mainMenu = new MainMenuPanel();
add(mainMenu;MAIN_MENU_CONSTRAINTS);
validate();
repaint(0,0,getWidth(),getHeight());
setVisible(true);
}
private void init() {
setVisible(false);
setTitle("Test");
// set card-layout
setRootPaneCheckingEnabled(false);
CardLayout cl = new CardLayout();
this.setLayout(cl);
// expand frame to whole display size
setExtendedState(MAXIMIZED_BOTH);
// set unclosable
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
public void update (Mode mode) {
switch (mode) {
case MAIN_MENU:
changeCard(MAIN_MENU_CONSTRAINTS);
break;
}
}
public void changeCard(String card) {
// update cards
CardLayout cl = (CardLayout) getLayout();
cl.show(this, card);
}
}
And here's the Panel:
public class MainMenuPanel extends Panel implements ActionListener{
private JButton startButton;
private JButton quitButton;
private final String START_ACTION_COMMAND = "START";
private final String QUIT_ACTION_COMMAND = "QUIT";
private MainMenuPanelListenerImpl listener;
public MainMenuPanel() {
super();
init();
initComponents();
configureComponents();
configureListeners();
addComponents();
revalidate();
}
private void init() {
setLayout(null);
}
private void initComponents() {
startButton = new JButton();
quitButton = new JButton();
}
private void configureComponents() {
startButton.setText("Start");
quitButton.setText("End");
startButton.setBounds((int)(0.5*getWidth()-200), (int)(0.5*getHeight()-75), 400, 75);
quitButton.setBounds((int)(0.5*getWidth()-200), (int)(0.5*getHeight()+25),400,75);
}
private void configureListeners() {
startButton.addActionListener(this);
startButton.setActionCommand(START_ACTION_COMMAND);
quitButton.addActionListener(this);
quitButton.setActionCommand(QUIT_ACTION_COMMAND);
}
private void addComponents() {
add(startButton);
add(quitButton);
startButton.validate();
quitButton.validate();
}
#Override
public void actionPerformed(ActionEvent e) {
switch (e.getActionCommand()) {
case START_ACTION_COMMAND:
listener.start();
break;
case QUIT_ACTION_COMMAND:
System.exit(0);
break;
}
}
public void setListener(MainMenuPanelListenerImpl listener) {
this.listener = listener;
}
}
After you paint the elements, you put the setvisible(true) because if you put it before, the Jframe will paint no elements
Well first of all you mix the old AWT-Components like Panel with newer SWING-Components like JFrame. Those don´t really work well together so I would try to fix that first. I would highly recommend using SWING or if you want to learn the newest Java GUI Library then JavaFX.
Don´t use the method repaint in the constructor of your JFrame, actually you shouldn´t use repaint in SWING at all. Nor do you need validate in the constructor. If you want to position your JFrame somewhere you should use something like this this.setLocation(0,0)
And to the main question: The panel probably only shows it´s components after resizing because you add it to the JFrame the wrong way. In SWING there is something called a content pane where you should add all of your stuff onto (except JMenuBar but that is a different story).
Simply set the layout of the content pane to the card layout that you want to use and then add your panel onto the content pane.
Here a link regarding the panel levels: https://docs.oracle.com/javase/tutorial/uiswing/components/toplevel.html
I'm working on an RCP application that's in a transition from a Swing version. So we have a lot of UI components that still need to live in the Swing world during this transition. I'm able to properly place the existing Swing components in AWT-SWT bridge frames.
I've wrapped these Swing components in a JScrollable pane before adding them to the bridge so that I don't have to resize the containing-part when the size of the Swing UI elements change. The code where I place an old Swing component in a part looks like this:
#PostConstruct
public void postConstruct(final Composite parent) {
/* Create embedding composite */
final Frame bridgeFrame;
final Composite embed;
embed = new Composite(parent, SWT.EMBEDDED);
embed.setLayout(new FillLayout());
bridgeFrame = SWT_AWT.new_Frame(embed);
bridgeFrame.setLayout(new BorderLayout());
bridgeFrame.add(
new JScrollPane(getTestPanel()),
BorderLayout.CENTER);
}
My Swing component has a behavior where when the user clicks a button, things that were hidden in the component are made visible, or new UI elements are added to the Swing component. For example:
private JPanel getTestPanel() {
final JPanel output;
final JButton eastBttn, westBttn;
output = new JPanel();
eastBttn = new JButton("East Button");
westBttn = new JButton("West Button");
output.setLayout(new BorderLayout());
output.add(eastBttn, BorderLayout.EAST);
output.add(westBttn, BorderLayout.WEST);
eastBttn.addActionListener(evt -> {
System.out.println("East Button Clicked");
output.add(new JLabel("East Button Clicked"), BorderLayout.CENTER);
});
return output;
}
My problem is, when the elements in the Swing-component change, the parent bridge-frame doesn't properly get rendered.
When the parts are first created, my application looks like this:
After I click on the EastButton it's supposed to add a text label in the center of that bridge frame. However, nothing changes in the application view.
But, when I even begin to resize the containing part-sash a little, the part containing the bridge-frame updates correctly:
What can I do to make the bridge-frame update containing part update automatically?
To test whether this was a repainting issue on the bridge-frame, I had a menu item which would trigger a repaint / revalidate / pack of the bridge-frame, but that didn't solve the issue. I suspect it has something to do with the renderer of the containing part, but have no idea how to go about addressing it.
The same a problem exists in a pure Swing solution:
public static void main(String[] args) {
JFrame bridgeFrame = new JFrame("Test");
bridgeFrame.setSize(400, 400);
bridgeFrame.setLayout(new BorderLayout());
bridgeFrame.add(new JScrollPane(getTestPanel()), BorderLayout.CENTER);
bridgeFrame.setVisible(true);
}
You need to add an output.doLayout() in your event handler.
I eventually got around the problem by attaching a custom ControlListener / ComponentListener to the part containing the bridge. If any changes within the workings of the bridge-frame caused it to resize to beyond the parent, I'd have the listener resize it to fit within the parent thus forcing the scroll-pane to take over.
Here's my listener:
public class BridgeComponetAdapter
extends ComponentAdapter
implements ControlListener {
private final Composite parent;
private final Frame bridgeFrame;
private Point parentSize;
public BridgeComponetAdapter(
final Composite parent,
final Frame bridgeFrame) {
this.parent = parent;
this.bridgeFrame = bridgeFrame;
bridgeFrame.addComponentListener(this);
parent.addControlListener(this);
}
#Override
public void componentResized(final ComponentEvent e) {
System.out.println(e);
if (e.getSource() != bridgeFrame)
return;
final Dimension currentBridgeSize;
currentBridgeSize = bridgeFrame.getSize();
if (currentBridgeSize.getWidth() > parentSize.x
|| currentBridgeSize.getHeight() > parentSize.y) {
bridgeFrame.setSize(parentSize.x, parentSize.y);
}
}
#Override
public void controlMoved(final ControlEvent e) {}
#Override
public void controlResized(final ControlEvent e) {
System.out.println(e);
if (e.getSource() == parent)
parentSize = parent.getSize();
}
}
It's not an elegant solution; I'm still open to other ideas to solve the problem.
I am currently trying to code a GUI for an assignment as extra credit, as a learning opportunity. I need to have a menu of buttons, with each button effectively changing the main panel to enter or display data. Right now, I have a class called buttonContainer, which holds the main menu, and mainPanel, which holds the main panel for the entire GUI. Basically I need a way to have buttonContainer add and remove elements from its parent, mainPanel- with the two of them remaining seperate files.
My buttonContainer class looks like this:
import java.awt.event.*;
import java.awt.*;
import javax.swing.*;
public class buttonPanel extends JPanel implements ActionListener
{
private JButton load, save, list, find, input, sort, exit;
private JPanel BtnContainer, parent;
private newContactPanel newContact;
public buttonPanel()
{
load = new JButton("Load Contacts");
save = new JButton("Save Contacts");
list = new JButton("List Contacts");
find = new JButton("Find Contact");
sort = new JButton("Sort Contacts");
input = new JButton("New Contact");
exit = new JButton("Exit Program");
newContact = new newContactPanel();
parent = this.getParent();
BtnContainer = new JPanel();
BtnContainer.setLayout(new GridLayout(0,1));
BtnContainer.add(load);
BtnContainer.add(save);
BtnContainer.add(list);
BtnContainer.add(sort);
BtnContainer.add(find);
BtnContainer.add(input);
BtnContainer.add(exit);
add(BtnContainer);
}
#Override
public void actionPerformed(ActionEvent e)
{
if (e.getSource() == input)
{
//Change panel command here
}
}
}
With the mainPanel code looking like this:
import java.awt.event.*;
import java.awt.*;
import javax.swing.*;
public class mainPanel extends JPanel //implements ActionListener
{
private buttonPanel MainMenu;
private newContactPanel newContact;
private JPanel wrapper;
public mainPanel()
{
wrapper = new JPanel();
this.setLayout(new BorderLayout());
wrapper.setLayout(new BorderLayout());
MainMenu = new buttonPanel();
newContact = new newContactPanel();
wrapper.add(MainMenu, BorderLayout.WEST);
add(wrapper, BorderLayout.WEST);
}
}
contactPanel is a different panel, that I want buttonPanel to trigger mainPanel to show. Is there any easy way of refrencing the parent class like this, while keeping the two classes separate?
I know variants of this question have been asked before, but, nothing I read here seemed to get done what I wanted. Several of them didn't really match exactly what I was looking for- most of them were from the same file. several used a getParent()- but if I try to use it, it only grabs a Container, and not a JPanel.
EDIT: Thanks to the people who answered. A couple of good ideas were presented- which helped me realize I forgot to actually add the action listener to the button. This question has been fully solved!
Basically I need a way to have buttonContainer add and remove elements from its parent, mainPanel- with the two of them remaining
seperate files.
You can use SwingUtilities.getAncestorOfClass(class, comp) from within your ButtonContainer class as you know it will be a child of that class. For example:
class ButtonContainer extends JPanel implements ActionListener {
...
#Override
public void actionPerformed(ActionEvent e) {
MainPanel mainPanel = (MainPanel)SwingUtilities.getAncestorOfClass(MainPanel.class, ButtonContainer.this);
if (mainPanel != null) {
// Change panel command here
}
}
}
Off-topic
Please read Java Code Conventions and stick to them. Class' names start with a capital letter; variables and methods names start with lower case.
you can make wrapper public static
public static JPanel wrapper;
then from buttonPanel you can use this code
mainPanel.wrapper.remove(<whatever component>);
mainPanel.wrapper.add(<whatever component>);
mainPanel.wrapper.validate();
mainPanel.wrapper.repaint();
i think this will work
I have the problem of a non displaying swing component. Here is how I have structured my code:
Thats my SelectionComponents class:
public void init() {
placeSelectionWithButtons();
}
private void placeSelectionWithButtons() {
JPanel selectionArea = new JPanel(new FlowLayout(FlowLayout.CENTER));
marketList = new JComboBox();
countryList = new JComboBox();
selectionArea.add(marketList);
selectionArea.add(countryList);
repaint();
}
With the init function I am initializing the method to Place the Buttons and Comboboxes.
Furthermore I want to put everything together in my MainPanel class:
I am just initializing this one method(will initialize more later!!!):
public void init(){
log.info("enterMainTabPanel init method");
selectionPanel.init();
}
Finally I am adding it to the method, when I created the TabBar:
public void createTabBar() {
log.info("add Tab Bar");
tabbedPane = new JTabbedPane();
//sets the first Tab
mainTabPanel.init();
tabbedPane.addTab("Main", mainTabPanel);
tabbedPane.setMnemonicAt(0, KeyEvent.VK_1);
...
My problem is that my TabBar gets created and all methods are callen(have viewed the log entries). However nothing displays inside the Tab Content?
Any recommendations what I should change or add?
I appreciate your answer!
The component hierarchy is not clear from your example code.
First check if you have added the TabBar to the content pane of your frame. Then verify that you have added the selectionArea to your TabBar.
From an EntryPoint class I load a custom build westPanel. From this WestPanel I would like to replace the center of the DockLayoutPanel present on my EntryPoint class.
Here is my EntryPoint class:
public class MainEntryPoint implements EntryPoint {
private VerticalPanel mainPanel = new VerticalPanel();
private DockLayoutPanel dockLayoutPanel = new DockLayoutPanel(Unit.EM);
private NorthMenu northMenu = new NorthMenu();
private VerticalPanel mainPanel = new VerticalPanel();
//other panels
#Override
public void onModuleLoad() {
dockLayoutPanel.addNorth(northMenu, 40);
dockLayoutPanel.add(mainPanel);
//add other panels
RootLayoutPanel panel = RootLayoutPanel.get();
panel.add(dockLayoutPanel);
}
}
WestPanel should replace DockLayout's mainPanel with a MyOtherPanel:
public class WestMenu extends Composite {
private StackLayoutPanel stackLayoutPanel = new StackLayoutPanel(Unit.EM);
public WestMenu(){
Tree configuration = new Tree();
configuration.addSelectionHandler( new SelectionHandler(){
#Override
public void onSelection(SelectionEvent event) {
MyOtherPanel builderPanel = new MyOtherPanel();
RootLayoutPanel panel = RootLayoutPanel.get();
DockLayoutPanel dlp = (DockLayoutPanel)panel.getWidget(0);
dlp.add(builderPanel);
}
});
//other init configurations
initWidget(stackLayoutPanel);
}
}
I keep on getting an Exception saying that I can not replace it. What is the best way to replace/change the center panel of a DockLayoutPanel?
thanks.
You need to explicitly remove the center (see javadoc of the protected insert method in DockLayoutPanel):
dlp.remove(currentCenterPanel);
But that's not very developer friendly, as you need to keep track of the center widget and always make sure you call remove before adding. I don't know why they did it like this.
Another solution could be to simple put a SimpleLayoutPanel as center widget and set your own center widget on this panel, via setWidget. That way you don't have to do the remove.
The latter technique also makes it possible to combine the implementation with the ActivityManager by setting the SimpleLayoutPanel as the display in ActivityManager.setDiplay(...). As your implementation looks like the main content of your application, the ActiviyManager might be useful here.