Suppose I have the following layout for my page:
vertical panel mainbody = new VerticalPanel;
//beginning of 1st sub-vertical panel
VerticalPanel first_panel = new verticalPanel();
first_panel.add(...);
//other such stuff, end of first_panel
mainbody.add(first_panel);
//beginning of 2nd sub-vertical panel
VerticalPanel second_panel = new verticalPanel();
second_panel.add(...);
//other such stuff, end of first_panel
mainbody.add(second_panel);
//beginning of 3rd sub-vertical panel
VerticalPanel third_panel = new verticalPanel();
third_panel.add(...);
//other such stuff, end of first_panel
mainbody.add(third_panel);
//end of mainbody
RootPanel.get().add(mainbody);
I want to modularize it, such that each sub panel (first_panel, second_panel and third_panel) belong to individual files, so that after some import, I can just code this in the main page to do the trick:
vertical panel mainbody = new VerticalPanel;
mainbody.add(first_panel);
mainbody.add(second_panel);
mainbody.add(third_panel);
//end of mainbody
RootPanel.get().add(mainbody);
The sub-panels themselves may use other sub-panels, for which the modularization should cascade. Now what do I need to do to enable this? The Google documentation is not quite clear to me. Specifically,
How do I define those panels in individual files (packages or folders) so that they can be imported into the main file?
How do I import them (somewhat like include in PHP)?
What changes do I need to make to the xml file (if any is needed)?
How to define the same set of rules for the imported files also, so that the imports cascade? That is, if a imports b, and b imports c and d to construct itself, both c and d are imported into the main file dutring import?
Will the CSS rules in the main CSS file be enough for all imported panels?
If someone can explain this from the viewpoint of the default StockWatcher app which comes packaged with GWT (so that we can have some common ground for understanding the directory structure), it will be easy for me to understand.
You need to make a Widget out of the panels.
package com.example.widgets // Make this package whatever you want
import com.google.gwt.user.client.ui.Composite
public class FirstPanel extends Composite{
private VerticalPanel verticalPanel;
public FirstPanel(){
verticalPanel = new VerticalPanel();
// All composites must call initWidget() in their constructors.
initWidget(verticalPanel);
// For your CSS
setStyleName("example-SomeStyle");
// Continue constructing object ...
}
}
The initWidget() needs to be called exactly once every time the constructor is used. It sets the widget to be wrapped by the composite. Check the documentation here.
Then you'll be able to use it like so
VerticalPanel mainPanel = new VerticalPanel();
FirstPanel firstPanel = new FirstPanel();
mainPanel.add(firstPanel);
The above should answer point 1
If your Widget isn't in the same package as the code above you'll need to import it. For the example above: import com.example.widget.FirstPanel
No changes need to be made in the XML file
Yes, the imports will cascade as you described.
The CSS Rule in the main CSS should be enough as long as you declare the style names in the widgets. You can do that by calling setStyleName("example-SomeStyle"); as you can see in the example above.
What you are asking about is called custom widgets. You can create a custom widget to represent first_panel, another one to represent second_panel, etc. Then you can make widgets that consist of other widgets, if necessary. Each custom widget is a separate class - it will be represented by a separate file (or two files if you use Ui:Binder for your custom widget).
You can read more about custom widgets here:
https://developers.google.com/web-toolkit/doc/latest/DevGuideUiCustomWidgets
Related
I have created a GUI with Java Swing and wanting to create a custom toolbar according to my modules. Below are the images am wanting to use:
These images are placed in the same level as the src folder within my application. I am aware that I can perhaps create a jar with these images so that I can easily access them from within my application but do not know how. I have spent hours trying to make this work.
Below is my GUI that I have created ad wanting to beautify with these images for the toolbar else create an array of labels that will act as a navigation but either approach I couldn't get it to work.
The code below was my last attempt on this:
JToolBar toolbar1 = new JToolBar();
ImageIcon client = new ImageIcon("clients.png");
ImageIcon timesheet = new ImageIcon("timesheets.png");
JButton clientTB = new JButton(client);
JButton timesheetTB = new JButton(timesheet);
toolbar1.add(clientTB );
toolbar1.add(timesheetTB);
add(toolbar1, BorderLayout.NORTH);
I even moved these images and placed them within the class that's calling them.
What could I be doing wrong, please help?
You have a look at the JavaDocs for ImageIcon(String), the String value is "a String specifying a filename or path"
This is a problem, because your images aren't actually files, any more, they have been embedded within your application (typically within the resulting jar file) and no longer be treated like "normal files".
Instead, you need to use Class#getResource which searches the application's classpath for the named resource, something like...
// This assumes that the images are in the default package
// (or the root of the src directory)
ImageIcon client = new ImageIcon(getClass().getResource("/clients.png"));
Now, I have a personal dislike for ImageIcon, because it won't tell you when the image is loaded for some reason, like it can't be found or it's the wrong format.
Instead, I'd use ImageIO to read the image
ImageIcon client = new ImageIcon(ImageIO.read(getClass().getResource("/clients.png")));
which will do two things, first, it will throw a IOException if the image can't be loaded for some reason and two, it won't return until the image is fully loaded, which is helpful.
See Reading/Loading an Image for more details
First time using the stackoverflow. So, please don't be too harsh :)
I have a little Java project. We are learning how to built GUI with swing. I am stuck with methodology.
I have a JFrame for GUI and I am creating 4 JPanels for:
Menu (Menu Class)
Buttons (Buttons Class)
ActionArea (ActionArea Class)
Statusbar (StatusBar Class)
I have been asked to have same options in the Menu and Buttons. i.e. New File or Open File options will be available in the Menu and Buttons sections.
I don't want to duplicate the code and copy into Menu Class and Buttons Class. I believe there is a way to use only one function from both classes.
Could somebody help me to achieve this?
Here is main code:
import java.awt.BorderLayout;
import javax.swing.JFrame;
public class GUI extends JFrame {
private Menu menu;
private Buttons buttons;
private ActionArea actionArea;
private StatusBar statusBar;
public GUI() {
super("New GUI");
this.setSize(800, 600);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setLayout (new BorderLayout());
this.menu = new Menu();
this.buttons = new Buttons();
this.actionArea = new ActionArea();
this.statusBar = new StatusBar();
this.setJMenuBar(this.menu);
add(this.toolbar, BorderLayout.NORTH);
add(this.actionArea, BorderLayout.CENTER);
add(this.statusBar, BorderLayout.SOUTH);
}
}
lets say the function name is newFile();
I don't want to write this function one for menu class and one for buttons class.
Thanks in advance to all
EDIT:
this.menu = new Menu(); creates menuitems with required actions in Menu class
this.buttons = new Buttons(); creates jbuttons with required actions in Buttons class
actions are exactly same. Code is doubled. This is the problem.
Use a Swing Action. See How to use Actions for details on using them in buttons and menu items.
you can use Action class which is an extension of ActionListener....there are several properties you can set in objects of these class...you can check out the line:
Tutorial for Using Action classes
and for API: Action classes API
it may help you..
You can make your Button class to take the object of Menu class as parameter in its constructor. Now, with this object, you can get access to the Action classes of your Menu class, and then, you can use them for your button.
If you still can't understand, please provide the code of your Button and Menu classes.
import javax.swing.*;
public class SlideShow {
JFrame slide = new JFrame("Slide Show");
public SlideShow(){
slide.setSize(300,400);
slide.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
slide.setVisible(true);
slide.setLocationRelativeTo(null);
JPanel panel = new JPanel();
JLabel label = new JLabel(new ImageIcon("Images/picture1"));
panel.add(label);
slide.add(panel);
}
public static void main(String[] args){
SlideShow slide = new SlideShow();
}
}
I have to create a simple Java GUI that displays some cards. First, I just wanted to test it by displaying one card. For some reason I can't seem to figure out why nothing is being displayed.
You haven't actually used a proper file name "Images/picture1". Should be something like "Images/picture1.png" with the file format
Also image files, generally should be read from the class path, if you plan on having them embedded to the program. To do so, you will first need to put the file in the class path. With most IDE build configurations it's as simple as placing the image in the src. So
ProjectRoot
src
images
picture1.png
Then you would read it like
new ImageIcon(getClass().getResource("/images/picture1.png"));
A better approach would be to use ImageIO.read(). If the file path is incorrect, it will throw an exception, so you know where you're going wrong
Image image = ImageIO.read(getClass().getResource("/images/picture1.png"));
ImageIcon icon = new ImageIcon(image);
You will need to put it in the try/catch block
Also do what codeNinja said about the setVisible() after adding component. Also preferably pack() the frame, instead of setSize()
You need to set the Frame visible after you add all necessary components to it. Move slide.setVisible(true); Down to the bottom of the constructor like this:
...
slide.add(panel);
slide.setVisible(true);
Alternatively you can add slide.revalidate(); at the bottom of your constructor.
I am trying to make a JTabbedPane in Java 7 on OSX that has tabs positioned to the left with their text horizontal (instead of vertical). However, with the code:
import javax.swing.*;
import java.awt.Dimension;
class Probs extends JDialog {
JTabbedPane options = new JTabbedPane();
Probs(JFrame owner) {
//main constructor
super(owner, "User Preferences", true);
//set the tabs to be left aligned
options.setTabPlacement(JTabbedPane.LEFT);
//construct the authorization panel
JPanel authorization = new JPanel();
authorization.add(new JLabel("test"));
options.addTab("test", authorization);
add(options);
setSize(new Dimension(300,300)); //should use pack here
setResizable(false);
setLocationRelativeTo(null);
setVisible(true);
}
public static void main(String[] args) {
JFrame test = new JFrame();
new Probs(test);
test.dispose();
}
}
I get a dialog box which looks like: this image
I would like the tab text to be horizontal (the 'test' title on the tab be oriented horizontally instead of vertically).
I searched around on Google for a while and have only run into occurrences wherein people wanted to achieve vertical text on their tabs, I could not manage to locate any in which people wanted to have horizontal text (what I am trying to achieve).
In particular, I am trying to achieve something which exactly looks like the image mentioned in the first post of this question. It is basically the exact opposite of that question because the person in that tab started with what I am trying to achieve (I believe). Basically, I am trying to determine how to create the image displayed in the first post of that question.
Can someone please tell me how to have left-oriented tabs while preserving horizontal tab titles (as opposed to vertical)?
Thank you for your time and assistance.
Again, since I can't replicate the problem, Try this suggestion:
JPanel authorization = new JPanel();
authorization.add(new JLabel("test"));
options.addTab("", authorization);
JLabel labTab2 = new JLabel("test"); // create a label
options.setTabComponentAt(0, labTab2); // set it to the component
The alignment is determined by your operating system. If you want to change the alignment of the tab text, you have to change the look and feel of your swing application. This worked for me. See here.
The system look and feel at MacOSX didn't support what you want in JTabbedPane. You must create a customized JComponent to do this or to set the look and feel of your application to cross platform (java metal) as stated before by #MonkeySupersonic.
I suggest the readings:
Apple Java Development Guide (section: User Interface Toolkits for Java) - https://developer.apple.com/library/content/documentation/Java/Conceptual/Java14Development/04-JavaUIToolkits/JavaUIToolkits.html
mac User Interface Guidelines - https://developer.apple.com/macos/human-interface-guidelines
I am brand new to GWT and am trying to achieve the following:
Here's the code that I've cooked up:
public class MyWebApp implements EntryPoint {
// The main container for everything the user sees (the "view")
private LayoutPanel mainPanel;
// Simple HTML for the header ("MyWebApp") and subsequent <hr/>
private SafeHtml header;
// The three links "Dashboard", "Monitors" and "Help Desk"
private HorizontalPanel navMenu;
// The empty content that gets populated when user clicks one of
// the 3 links.
private Panel menuContent;
#Override
public void onModuleLoad() {
// The initial fragment contains the header, nav menu and empty "content" div.
// Each menu/screen then fills out content div.
initMainPanel();
RootPanel.get().add(mainPanel);
}
private void initMainPanel() {
SafeHtmlBuilder headerBuilder = new SafeHtmlBuilder();
navMenu = new HorizontalPanel();
// Leaving null until user clicks on one of the 3 menus.
// Then the menu will decide what panel gets injected for
// this panel.
menuContent = null;
// Create the simple HTML for the header.
headerBuilder.append("<h1>MyWebApp</h1><hr/>");
// Create the navMenu items.
Hyperlink dashboardLink, monitorsLink, helpDeskLink;
// Homepage is http://www.mywebapp.com
// I want the dashboardLink to inject menuContent and "redirect" user to
// http://www.mywebapp.com/dashboard
dashboardLink = new Hyperlink("???", "???");
// http://www.mywebapp.com/monitors
monitorsLink = new Hyperlink("???", "???");
// http://www.mywebapp.com/help-desk
helpDeskLink = new Hyperlink("???", "???");
navMenu.add(dashboardLink);
navMenu.add(monitorsLink);
navMenu.add(helpDeskLink);
// Add all widgets to the mainPanel.
mainPanel.add(new HTML(headerBuilder.toSafeHtml().toString()));
mainPanel.add(navMenu);
mainPanel.add(menuContent);
// Position and size the widgets (omitted for brevity).
// mainPanel.setWidgetHorizontalPosition(...);
}
private HTML getDashboardMenuContent() {
return new HTML("This is the dashboard.");
}
private HTML getMonitorsMenuContent() {
return new HTML("These are the monitors.");
}
private HTML getHelpDeskMenuContent() {
return new HTML("This is the help desk.");
}
}
Most importantly:
How do I "wire up" the Hyperlinks so that when the user clicks them, I can call the appropriate getXXXMenuContent() method, and then add that to menuContent?
But also:
I feel like I'm doing something wrong here: mainPanel.add(new HTML(headerBuilder.toSafeHtml().toString())); - if so what is it?!? How should I be adding a simple <h1> and <hr/> in a way that's secure (hence the use of the Safe* objects), efficient, and conforming to recommended practices?
Should I be implementing UiBinder here? If so, would I make UiBinders for each menu's content or for the entire mainPanel, or both?
Thanks in advance!
Hyperlink widgets trigger navigation. You don't want to handle clicks on them, you want to handle navigation (that could be triggered by clicking a Hyperlink or using the browser's back/forward buttons, a bookmark or link from elsewhere –including Ctrl+clicking a Hyperlink to open it in a new window/tab–, etc.)
To react to those navigation events, use History.addValueChangeHandler; and to handle the initial navigation on application start, call History.fireCurrentHistoryState() (after you add your handler of course).
More details in: https://developers.google.com/web-toolkit/doc/latest/DevGuideCodingBasicsHistory
Would be better to split other questions to... other questions, but here are the answers anyway:
I feel like I'm doing something wrong here: mainPanel.add(new HTML(headerBuilder.toSafeHtml().toString())); - if so what is it?!? How should I be adding a simple <h1> and <hr/> in a way that's secure (hence the use of the Safe* objects), efficient, and conforming to recommended practices?
The HTML widget has a constructor taking a SafeHtml so you don't need to call toString().
If you're only using a constant, you don't need a SafeHtmlBuilder; use SafeHtmlUtils instead. But constants are no more or less secure with or without SafeHtml, SafeHtml just makes it easier to find all occurrences of HTML in your code, to help in doing a security review of your app (BTW, we're doing HTML, so <hr>, not <hr/>; if you really want it to look like XML/XHTML, then use <hr /> but you're only cheating yourself here)
Should I be implementing UiBinder here? If so, would I make UiBinders for each menu's content or for the entire mainPanel, or both?
If you don't feel the need for UiBinder, you don't have to use it. But in this case it won't change anything: you're not handling widget events, but history events.
Something like
dashboardLink.addClickHandler(
new ClickHandler()
{
public void onClick( ClickEvent event )
{
mainPanel.setWidget( getDashboardMenuContent() );
}
} );
You should note that Hyperlink.addClickHandler(...) is deprecated and it is recommended to use Anchor.addClickHandler(...) instead.
As for the other questions: It is a lot more elegant and easier to build UI's with UIBinder, so definitely look into that, but do try to make "it" work first to avoid the added complexity of the .ui.xml setup :-)
Cheers,
I have one simple piece of advice to give you. Use what the framework has to offer.
The HTML widget should be your last escape. There are so many widgets that there is no need for you to write html almost anywhere in your code.
So instead of headerBuilder, you can user the following piece of code
Label header = new Label("MyWebApp");
header.setStyleName("headerStyle",true);
You can set the style properties in an external Css file and add the reference inside the base html file or the gwt.xml file. So that answers your question about mainPanel.add(new HTML(headerBuilder.toSafeHtml().toString()));
In respect to the Hyperlink. If you choose to use hyperlinks, remember that the most effective usage is with the MVP pattern better known as Places and Activities (Lots of information on the web)
If you want something simpler instead the MenuBar and MenuItem classes should do the trick.
Look here for an example on how to use the MenuBar to control your application. There are many other ways but why not use the tools provided?
Also the UIBinder Vs the Designer/Classes methods is extensively discussed on stackoverflow resulting to a matter of choice and programming familiarity/preference.