I was wondering if there is a way or a method that allows me to get the current JEditorPane being displayed. For example I have a JFrame where I can create several tabs. Whenever a tab is created a new JEditorPane object is created and the content of that pane are displayed in the tab. I've implemented a ChangeListener that currently just gets me the index of the current tab whenever I open a new one, close one or navigate between tabs. What I want to do is whenever a new tab is opened or navigated to I want to get the current JEditorPane object that resides at this tab. Is there any way in which I can achieve that?
Sorry if the question is a bit vague.
Thanks in advance.
The best way to do this would be to subclass JPanel and add your custom JPanel to the tabbed pane instead:
public class EditorPanel extends JPanel {
private JEditorPane editorPane;
// ...
public EditorPanel() {
// ...
editorPane = new JEditorPane( ... );
super.add(editorPane);
// ...
}
// ...
public JEditorPane getEditorPane() {
return editorPane;
}
}
Adding a new tab:
JTabbedPane tabbedPane = ... ;
tabbedPane.addTab(name, icon, new EditorPanel());
And then when you need to access it using the tabbed pane:
Component comp = tabbedPane.getComponentAt(i);
if (comp instanceof EditorPanel) {
JEditorPane editorPane = ((EditorPanel) comp).getEditorPane();
}
This is a better alternative to maintaining a separate list and trying to maintain it alongside the tabbed pane's indices.
Related
I am just exploring Vaadin 7 and I'm a bit frustrated to face a wall right at the start. Experienced in Swing I was happy to find Vaadin layouts are so simple and they are just like other components (they actually are Components, according to the class hierarchy). However, I faced a problem building my first Window.
So let's say I have a CustomComponent of such composition:
VerticalLayout
|
--TextArea
|
--Button
Which in the code will look like this:
public class SOComplicatedComponent extends CustomComponent {
private VerticalLayout mainLayout;
private TextArea textArea;
private Button button;
public SOComplicatedComponent() {
buildMainLayout();
setCompositionRoot(mainLayout);
}
private VerticalLayout buildMainLayout() {
// common part: create layout
mainLayout = new VerticalLayout();
mainLayout.setWidth("100%");
mainLayout.setHeight("100%");
// top-level component properties
setWidth("100.0%");
setHeight("100.0%");
// textArea
textArea = new TextArea();
textArea.setValue("hey, this button is supposed to be under me!");
textArea.setSizeUndefined();
mainLayout.addComponent(textArea);
//button
button = new Button("Ooops");
button.setSizeUndefined();
mainLayout.addComponent(button);
return mainLayout;
}
}
Then I'm constructing a Window in a following way:
public class MyUI extends UI{
#Override
protected void init(VaadinRequest request) {
...
Window window = new Window("Help me SO", new SOComplicatedComponent());
addWindow();
}
}
As a result I get a window with the TextArea and Button overlapping. When I resize the Window, contents stretch and the Layout becaomes OK, however I thought the Window is supposed to automatically fit to the contents size, isn't it?
OK, time for a final
QUESTION
I want the Button to be under the TextArea in my Window and make the Window size automatically fit its contents. What is the most proper way of achieving that in Vaadin 7?
Thanks
In this particular instance, there is no need for a separate Window - in Vaadin 7, Windows are actually child windows of the main UI; according to your comments, you do want a floating window. That's cool - but but a UI really should have some content, even if it's empty (otherwise rendering looks a little odd).
So,
You should simply be able to do
public class MyUI extends UI {
#Override
protected void init(VaadinRequest request) {
// You need to have some content on the UI, even if it's empty - otherwise it looks odd
// Here, I'm just adding an empty layout
VerticalLayout content = new VerticalLayout();
content.setSizeFull();
setContent(content);
// Adding a child window, and centering it for kicks
Window window = new Window("Help me SO", new SOComplicatedComponent());
window.center();
addWindow(window);
}
}
The AbsoluteLayout requires that you specify the location of your components. For a simple Vertical layout (i.e. TextField above Button) you would typically use the VerticalLayout
Also, setSizeFull means "make this component take all of the space allowed by it's container" -
which gets a bit confusing when you want the parent to make the child component as big as it needs to be, and no bigger. I think you really want to use "setSizeUndefined" for the CustomComponent too. So, putting all that together should give you this:
public class SOComplicatedComponent extends CustomComponent {
private VerticalLayout mainLayout;
private TextArea textArea;
private Button button;
public SOComplicatedComponent() {
buildMainLayout();
setCompositionRoot(mainLayout);
}
private VerticalLayout buildMainLayout() {
// common part: create layout
mainLayout = new VerticalLayout();
mainLayout.setSpacing(true);
mainLayout.setMargin(true);
// top-level component properties
/* CSA : SizeUndefined means "take as much space as my content needs" */
setSizeUndefined();
// textArea
textArea = new TextArea();
textArea.setValue("hey, this button is supposed to be under me!");
textArea.setSizeUndefined();
mainLayout.addComponent(textArea);
//button
button = new Button("Ooops");
button.setSizeUndefined();
mainLayout.addComponent(button);
return mainLayout;
}
}
For me, that renders like this :
I am building an application using the VAADIN framework.
I am trying to add a panel in a view containing a VerticalSplitPanel which contains two components (a button and a label for the moment).
Pretty straight forward but I'm having big problems getting it done.
I can identify that something happens, because I see the "split-divider" show when I run it in a browser, but no components inside the split-panel.
This is how I initialize the panel for the moment.
public class M2MInventory_SubscriptionsView extends AbstractView {
private Panel panel = new Panel();
private VerticalSplitPanel vSplit = new VerticalSplitPanel();
private Button upperButton = new Button("Upper Button");
private Button lowerButton = new Button("Lower Button");
public M2MInventory_SubscriptionsView() {
panel.setContent(vSplit);
vSplit.setFirstComponent(new Button("Upper"));
vSplit.setSecondComponent(new Label("Lower"));
addComponent(panel);
}
Can anyone spot an error in my ways?
Try to set panel height first. It will work but I'm not sure why.
The default layout of Panel is VerticalLayout with undefined height. It's strange, because I thought If you insert enough components in such a layout, it will grow.
I have created a JDialog which contains a JComboBox and a panel underneath which should display a different content based on the value selected in the JComboBox. I have created a JPanel (panel_1) which is added to the content pane of the dialog and an additional JPanel for each of the possible items in the JComboBox (for example panel_item_1 and panel_item_2 if it does have only 2 items). I have attached the following listener class in the JComboBox:
public class SelectedListener implements ActionListener {
private SettingsDialog dialog;
public SelectedListener(SettingsDialog dialog){
this.dialog = dialog;
}
public void actionPerformed(ActionEvent e) {
JComboBox cb = (JComboBox)e.getSource();
String selected_settings = (String)cb.getSelectedItem();
if(selected_settings.compareTo("Option 1") == 0){
dialog.panel_1 = dialog.panel_item_1;
dialog.panel_1.updateUI();
}else if(selected_settings.compareTo("Option 2") == 0 ){
dialog.panel_1 = dialog.panel_item_2;
dialog.panel_1.updateUI();
}
}
}
However this doesn't make the panel update with the new content. Any suggestion? Thanks in advance
which should display a different content based on the value selected in the JComboBox.
Read the section from the Swing tutorial on How to Use Card Layout which has a working example that does exactly what you want.
Edit:
dialog.panel_1 = dialog.panel_item_1;
The real problem is that you can't just change the reference to a variable and expect the component to show up on the panel. You still need to add the component to the panel before you do a revalidate() on the panel. So your code is like:
panel.remove(...);
panel.add(...);
panel.revalidate();
panel.repaint();
However, the better solution is to use a CardLayout which does all this work for you.
I want to create a function so that i can call add JLabel's, etc inside the JScrollPanel. I am not sure what the command is in NetBeans.
I tried doing JScrollPanel -> events -> container -> componentAdded to create the code below. But nothing shows up when i add code to that function.
private void initComponents() {
scrollPanel = new javax.swing.JScrollPane();
scrollPanel.addContainerListener(new java.awt.event.ContainerAdapter() {
public void componentAdded(java.awt.event.ContainerEvent evt) {
scrollPanelComponentAdded(evt);
}
}
private void scrollPanelComponentAdded(java.awt.event.ContainerEvent evt) {
System.out.println("main");
}
Any help would be great, thanks.
I don't use Netbeans and I'm not quite sure I understand exactly what you're trying to do, but the normal case for adding components to a scroll pane is to add a panel as the scroll pane's "viewport". The scroll pane is then like a window into that panel. If the panel is too big to fit into the scroll pane, the scrollbars will appear.
Here is a snippet to show what I mean. This might be what you're looking for in your initComponents method:
JPanel panel = new JPanel();
panel.add( ... ); // Add whatever components to the panel
scrollPanel = new JScrollPane();
scrollPanel.setViewportView(panel);
A ContainerListener will only be called when a component is actually added or removed from a container. In your above code, no other components are ever added to the scroll pane.
I am currently desigining a calculator panel using Java Swing. However, it's an extreme PAIN to line up all of the buttons because they are always resizing and repositioning themseleves whenever I add a new button or change the size of a button.
Is there a type of layout or something that can "lock" the buttons in position so they are not affected when I move/resize/add other buttons?
Thanks,
Bob
Extending what Tom said...
To allow a component to become invisible yet hold its place, you can place it in a CardLayout along with an empty label and just swap which is visible.
You can create a class to do this for you as follows The main just shows an example where if you click a button it's deleted while retaining its position. I put in showComponent/hideComponent and setVisible(t/f) - depends on the style you like.
This might not exactly answer what you're looking for, but might be a useful piece for part of your application.
public class Placeholder extends JPanel {
private static final long serialVersionUID = 1L;
private CardLayout cardLayout_;
public Placeholder(JComponent component) {
cardLayout_ = new CardLayout();
setLayout(cardLayout_);
add(component, "visible"); // the component
add(new JLabel(), "hidden"); // empty label
}
public void showComponent() {
cardLayout_.show(this, "visible");
}
public void hideComponent() {
cardLayout_.show(this, "hidden");
}
public void setComponentVisible(boolean visible) {
if (visible)
showComponent();
else
hideComponent();
}
public static void main(String[] args) {
JFrame f = new JFrame();
f.setLayout(new GridLayout(2,0));
for (int n = 1; n < 10; n++) {
JButton b = new JButton(n + "");
final Placeholder placeholder = new Placeholder(b);
f.add(placeholder);
b.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
placeholder.hideComponent();
}
});
}
f.pack();
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.setVisible(true);
}
}
I suggest instead of adding and removing buttons, you change their visibility property (setVisible). Some layout manager ignore non-visible components, so you may need to add a non-opqaue (or matching background) component in the same position that follows the preferred/minimum/maximum sizes of the original component. More simple you may want to use OverlayLayout.
You could use GridBagLayout to keep them in a grid, but allow them to resize
Extending what the others said...
Instead of making the components invisible, you can also disable them...
Of course, it depends on your application and your preferences.
Beside the above mentioned layouts, there are some freely available ones, like TableLayout and the versatile MigLayout.
It probably depends on the development environment you are using.
In Netbeans you can right-click the control container (form/panel) and select from a number of layout options. 'Absolute Layout' will let you position the controls without them all being resized automatically, although it won't let you place controls on top of each other.
I suggest you to check A Visual Guide to Layout Managers. Depending on the look and functionality you want there are different layouts that could work for you. If the main problem is the resize operation (of the parent JFrame o JPanel I assume), the Spring Layout allows you to establish constraints regarding the relative place of components.