How can I vertically align a label with a Combo in the first row of an adjacent Composite?
The label and the multi-row control are in a GridLayout with other controls, with left-alignment of the labels and the fields. The multi-row control is re-used elsewhere.
Ideally, the baselines of the text in the label and the Combo would be aligned. In practice, when the label and combo are siblings, vertically centering the two with SWT.CENTER is usually sufficient.
I can't just lower the label by a compile-time constant, because of differences in fonts and look-and-feels.
Ideas that have occurred to me include:
At runtime, while constructing the controls, ask Eclipse for the height of its combo widgets, somehow. Embed the label in a Composite and pad or align appropriately.
Put the label (possibly embedded in a Composite) in a StackLayout with a dummy Combo that's never displayed, to give the label cell the height of the first row in the sibling control. Center align the label within its parent.
Is there a simpler/cleaner approach?
I confirmed that the problem can be solved by the second approach I suggested in the question. If anyone has a better answer, please post.
This approach has these objects:
AbstractLabelWithHeightOfAnotherControl / custom StackLayout
<>-- Other control
Composite / GridLayout
<>-- Label / GridData( SWT.BEGINNING, SWT.CENTER, false, true )
The custom StackLayout has the width of the label, but the height of the other control.
This code provides an abstract class that supports the behavior for a variety of other controls.
public abstract class AbstractLabelWithHeightOfAnotherControl extends Composite {
private Label m_label;
private Control m_otherControl;
/** Constructor.
* #param parent
* #param style
*/
public AbstractLabelWithHeightOfAnotherControl(Composite parent, int style) {
super( parent, style );
StackLayout stackLayout = new MyStackLayout();
this.setLayout( stackLayout );
Composite layerLabel = new Composite( this, SWT.NONE );
GridLayout layerLabelLayout = new GridLayout( 1, false );
layerLabelLayout.marginWidth = 0;
layerLabelLayout.marginHeight = 0;
layerLabel.setLayout( layerLabelLayout );
m_label = new Label( layerLabel, SWT.NONE);
m_label.setLayoutData( new GridData( SWT.BEGINNING, SWT.CENTER, false, true ) );
m_otherControl = makeOtherControl( this );
stackLayout.topControl = layerLabel;
}
protected abstract Control makeOtherControl( #Nonnull Composite parent );
public Label getLabel() {
return m_label;
}
private final class MyStackLayout extends StackLayout {
MyStackLayout() {
this.marginHeight = 0;
this.marginWidth = 0;
}
#Override
protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) {
int width = m_label.computeSize( wHint, hHint, flushCache ).x;
int height = m_otherControl.computeSize( wHint, hHint, flushCache ).y;
if (wHint != SWT.DEFAULT) width = wHint;
if (hHint != SWT.DEFAULT) height = hHint;
return new Point(width, height);
}
}
}
The implementing class can just provide a method like this:
#Override
protected Control makeOtherControl( #Nonnull Composite parent ) {
return new Combo( parent, SWT.NONE );
}
What about creating a component like this:
+-------------------------------+
| +---------------------------+ |
| | +------+ +-------------+ | |
| | |Label | |Combobox | | |
| | +------+ +-------------+ | |
| +---------------------------+ |
| | +------+ +-------------+ | |
| | |Dummy | |Combobox | | |
| | +------+ +-------------+ | |
| +---------------------------+ |
| | +------+ +-------------+ | |
| | |Dummy | |Combobox | | |
| | +------+ +-------------+ | |
| +---------------------------+ |
+-------------------------------+
Have it created by a method that takes the label text as input. The Dummies are empty labels if you want. If the method label text is null you can omit the creation of the labels altogether or make all empty. That way you can reuse the multi combobox component with or without label.
Related
Is it possible to use a flowpane in the following way?
Have two components (img/label) aligned to the left and then multiple buttons on the right. Example:
+----------------------------------------------------------------+
| +------+ +----------+ +-----+ +-----+ |
| | Img | | Text... | | btn | | btn | |
| +------+ +----------+ +-----+ +-----+ |
+----------------------------------------------------------------+
I am adding the buttons for design / ease of use but am running into a brick wall. I would prefer not to have to change the 'holding panel'.
If not can it be simulated in css (float?)
Thanks
A FlowPanecan set margins. Here is an example that shows how to calculate the width of the margin so that the buttons are right aligned.
scene.widthProperty().addListener( ( observable, oldWidth, newWidth ) ->
{
final double spacerMargin = newWidth.doubleValue()
- scene.getRoot().getChildrenUnmodifiable().stream().mapToDouble( node -> node.getLayoutBounds().getWidth() ).sum();
FlowPane.clearConstraints( btn3 );
FlowPane.setMargin( btn3, new Insets( 0, 0, 0, spacerMargin ) );
} );
You basically subtract all the widths of the children of the FlowPane from the width of your scene.
Yes it is!
myFlow.add(griddy); // this gridlayout contains img and text
myFlowcontainer.add(Box.createRigidArea(new Dimension(5,0))); // Creating a space between.
The actual size will be defined by you
myFlow.add(griddy2); // The other element with the btn btn
That should seal the deal ;)
I currently have a populated SWT table with the following styles:
SWT.BORDER | SWT.FULL_SELECTION | SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL
used SWT.FULL_SELECTION to get the whole line selected if clicked.
but using table.getSelection() only returns the first column.
I don't have any tableviewer or something else set.
where did I make a mistake?
edit:
example:
if (table.getSelectionCount() > 0) {
for (TableItem item : table.getSelection()) {
System.out.println(item);
}
}
this returns only the first column
Since you are only calling System.out.println() on the whole TableItem, Java will internally use TableItem#toString() to convert it to a String.
The resulting string however, will not contain all the data of the TableItem.
Instead, you'll need to iterate over the columns to get the data using TableItem#getText(int column):
for(int i = 0; i < table.getColumnCount(); i++)
System.out.println(item.getText(i));
Program ScreenShot
I'm making a animation. When I press on a button it triggers a animation which makes a JPanel float in from the right side. The JPanel gets DeAnimated(JPanel exit animation) when the mouse leaves the JPanel, but the problem is that I have a JButton on the animated JPanel. So the panel does not only disappear when i move the mouse out of the animated JPanel but also when I move the mouse on the button (which is a component of the panel), which means that when I want to click on the button it disappears, because the MouseExit is fired when the mouse leaves the JPanel.
Look at the picture above where I marked certain areas.
Is the JPanel which is getting animated and disappears when i move over the button.
Is the button which causes the JPanel to be DeAnimated.
Is the area which should trigger the DeAnimation of the 1st JPanel.
I have been trying to fix this for a long time now, but I can't get it working. I would really appreciate it if you guys could help me. Thanks!
"but the problem is that I have a JButton on the animated JPanel. "
Don't put the button on the same panel then. Learn to use layout managers. With your image, I would use nested JPanels with BorderLayouts
The right side
JButton button = new JButton();
JPanel animatedPanel = new JPanel();
Add them to another JPanel
JPanel rightPanel = new JPanel(new BorderLayout());
rightPanel.add(button, BorderLayout.NORTH);
rightPanel.add(animatedPanel, BorderLayout.CENTER);
/** result **/
+-----+
| |
| |
+-----+
| |
| |
| |
| |
| |
+-----+
Then create another JPanel to hold the BigPanel and the RightPanel
JPanel mainPanel = new JPanel(new BorderLayout());
JPanel leftBigPanel = new JPanel();
mainPanel.add(leftBigPanel, BorderLayout.CENTER);
mainPanel.add(rightPanel);
/** result **/
*--------------------+-----+
| | |
| | |
| +-----+
| | |
| | |
| | |
| | |
| | |
+--------------------+-----+
The button no longer overlaps the right animated panel
Note : #override the getPreferredSize() in the JPanels for your desired dimension.
I am developing a GUI in java using Netbeans (7.0).
I have a JFrame including a JPanel and several elements inside this panel.
The layout type is free layout I think.
draft:
-------------------
|JFrame |
| |
| --------------- |
| |JPanel | |
| | | |
| | elem1 elem2 | |
| | elem3 elem4 | |
| | elem5 elem6 | |
| | | |
| |-------------- |
| |
-------------------
During my program is running I am hiding some of the elements being in one row (e. g. elem3 and elem4) by using setVisible(false).
Everything resizes as expected (JFrame and JPanel) except for the gaps.
It looks like that the elements are hidden correctly but there gaps are remaining so that in my example where I am hiding elem3 and elem4 a bigger gap between the row elem1/elem2 and elem5/6 remains.
Hopefully my problem was understandable :-)
Is there any way to fix this behavior?
Thanks in advance.
Steffen
Try removing that elements from jpanel instead of hiding but remember this will still not work for some layout. It depends on your layout to how to handle adding and removing of component.
with intend to avoid any missinterpretations:
if is TopLayoutContainer once visible then:
1/ for adding new JComponent is needed to call revalidate() and for compound JComponents f.e. with set programatically Item in JComboBox is needed call with repaint() too
2/ after removing JCmponent(s) you have to call revalidate() plus repaint()
3/ for example remove JComponents -> add new JComponents -> revalidate() plus repaint()
#Steffen Kuehn there are lots of possible problems, better would be to sent code that ilustrated your described issue
#Steffen Kuehn please check out the below code which presents the 'possible' problem you are experiencing. i.e. you are not revalidating and repainting the panel which was changed.
Please notice when you click the panel using left mouse button there is no repainting/revalidation, and at first it seems nothing is happening. Try to resize the frame. It calls the operations and you will see that the elements 5 & 6 are in fact visible. Thus if you want the changes to be instant use the right click which does visibility change and validation.
import java.awt.Color;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class FlowComponentsTest
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
final JPanel p = new JPanel();
for(int i = 1; i <= 20; i++)
{
JComponent c = new JTextField("I am element no. " + i);
//so any textfield will not steal the focus from the panel p
c.setFocusable(false);
p.add(c);
if(i == 5 || i == 6)
{
c.setForeground(Color.GREEN);
c.setVisible(false);
}
}
JFrame f = new JFrame();
f.addMouseListener(new MouseAdapter()
{
#Override
public void mousePressed(MouseEvent e)
{
JComponent c5 = (JComponent) p.getComponent(4);
JComponent c6 = (JComponent) p.getComponent(5);
c5.setVisible(!c5.isVisible());
c6.setVisible(!c6.isVisible());
if(e.getButton() == MouseEvent.BUTTON3)
{
System.out.println("Right click");
p.revalidate();
p.repaint();
}
}
});
f.setContentPane(p);
f.setSize(300, 330);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
});
}
}
I have a JTable with 3 column of which first column is a button and second column is id. Now when user clicks on the button of specific row that row should be deleted. Up to this point everything wo$rks fine. But another requirement is re-sequencing the table data. I mean the column id should be re-sequence. For example:
First table data:
| id | another-column
b1 | 1 | abc
b2 | 2 | xyz
b3 | 3 | def
b4 | 4 | qwe
Now when user deletes second row which have id=2 then table data should be as follows:
| id | another-column
b1 | 1 | abc
b3 | 2 | def
b4 | 3 | qwe
Here b1/b2/b3/b4 are buttons for deletion of particular row.
How can I do this?
It is fairly easy to set this sequential id value inside the getValueAt(row, col) of your Abstract Table Model.
public Object getValueAt(int row, int col) {
if (col == 1)
return int (row + 1);
.....
}
Set the model again inside the action event of your buttons. The model will repaint the JTable correctly after a button has been pressed.