How to drag tabs which are custom components in JTabbedPane? - java

I have simple JPanel that serves as tabComponent of JTabbedPane. It is MainTabComponent class:
public class MainTabComponent extends JPanel {
private JLabel label;
public MainTabComponent(String title, MainTabbedPane mainTabbedPane) {
// unset default FlowLayout gaps
super(new FlowLayout(FlowLayout.LEFT, 0, 0));
setOpaque(false);
label = new JLabel(title, Images.tabIconSaved, JLabel.LEADING);
add(label);
// add more space between the label and the button
label.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 5));
// tab button
JButton button = new TabButton();
add(button);
// add more space to the top of the component
setBorder(BorderFactory.createEmptyBorder(2, 0, 0, 0));
}
}
Next I need to allow user to drag tabs(that is MainTabComponent).
The problem is that method tabForCoordinate of TabbedPaneUI doesn't return correct tab index.
It returns always 0.
So I need to find out tab index on mouse click, but how to do this with custom tab?
Thank you!

Related

How to add scrolling feature to a JComponent on a JFrame?

My GUI consists of a Diagram class which extends JFrame. I've created a different class called DrawingTool which extends JComponent. The DrawingTool class is like a canvas area for users to drop and drag shapes. I've also added a button panel at the bottom of the JFrame for the users to click various buttons to choose their desired shape and control actions. I've added the button panel and an instance of the DrawingTool class to the Diagram class. How do I make the canvas area (DrawingTool) scrollable? The way I have attempted it is not working, I know I am missing something.
Here is the Diagram class:
public class Diagram extends JFrame {
JButton serverButton, vipButton, arrowButton, undoButton, dragButton, loadButton, submitButton;
JButton applicationButton;
int currentAction = 1;
Graphics2D graphSettings;
Color strokeColor = Color.BLUE, fillColor = Color.BLACK;
/**
* Constructor to generate new diagram with empty drawing board and button
* panel.
*/
public Diagram() {
// Define the defaults for the JFrame
this.setSize(1000, 1000);
this.setTitle("Diagram Tool");
//this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel buttonPanel = new JPanel();
// Swing box that will hold all the buttons
Box theBox = Box.createHorizontalBox();
// Make all the buttons in makeButtons by calling helper function
serverButton = makeButtons("Server", 2);
vipButton = makeButtons("VIPs", 3);
arrowButton = makeButtons("Arrow", 4);
undoButton = makeButtons("Undo", 5);
dragButton = makeButtons("Drag", 6);
loadButton = makeButtons("Load", 11);
applicationButton = makeButtons("Application", 8);
submitButton = makeButtons("Submit", 12);
// Add the buttons to the box
theBox.add(serverButton);
theBox.add(vipButton);
theBox.add(applicationButton);
theBox.add(arrowButton);
theBox.add(undoButton);
theBox.add(dragButton);
theBox.add(loadButton);
theBox.add(submitButton);
// Add the box of buttons to the panel
buttonPanel.add(theBox);
// Position the buttons in the bottom of the frame
JPanel container=new JPanel();
container.add(new DrawingBoard(),BorderLayout.CENTER);
JScrollPane jsp=new JScrollPane(container);
this.add(buttonPanel, BorderLayout.SOUTH);
this.add(jsp);
// Make the drawing area take up the rest of the frame
// Show the frame
this.setVisible(true);
}
Here is the DrawingBoard class:
private class DrawingBoard extends JComponent implements MouseListener, MouseMotionListener {
//declare variables
/**
* Constructor to initialize the drawing board
*/
public DrawingBoard() {
addMouseListener(this);
addMouseMotionListener(this);
// initializeCanvas();
}
//Rest of the code for DrawingBoard
}
This is how it looks now. I'd like to make the gray canvas area scrollable.
Diagram Image
What MadProgrammer said in the comments is just about right. You need to set some informations so your ScrollPanel knows how to behave. What is it's own size, the size of the components inside it, etc.
So normally you'll have a ContentPane, and inside of it panes with your content. To do a scrollable pane you only need to put the ScrollPane inside of your ContentPane and then set a viewport for your ScrollPane. A little code I used fully functional:
contentPane = new JPanel();
setContentPane(contentPane);
contentPane.setLayout(null);
JScrollPane scrollPane = new JScrollPane();
//Vertical and Horizontal scroll bar policy is set to choose when the scroll will be visible scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
scrollPane.setBounds(0, 217, 414, 505);
scrollPane.setPreferredSize(new Dimension(414, 414));
JPanel viewport = new JPanel();
viewport.setLayout(null);
viewport.setBounds(0, 0, 414, 505);
//Create your components here, then:
//viewport.add(component)
viewport.setPreferredSize(new Dimension(414, 150));
scrollPane.setViewportView(viewport);
contentPane.add(scrollPane);
Anything you put inside of your ViewPort
will be automaticaly scrolable, if it's size is bigger than the PreferredSize.
Note that all the dimensions I've put is only for example.

JLabels not showing in JPanel if bounds not set

I have the following code:
public JPanel getPanel() {
if(jpanel == null) {
jpanel = new JPanel();
jpanel.setLayout(new FlowLayout());
jpanel.setBounds(x, y, width, height);
jpanel.setBackground(Color.WHITE);
JLabel tituloLbl = new JLabel(titulo);
JLabel cantidadLbl = new JLabel(""+cantidad);
JLabel abejasLbl = new JLabel("Abejas");
//tituloLbl.setBounds(0, 0, 50, 15);
jpanel.add(tituloLbl);
jpanel.add(cantidadLbl);
jpanel.add(abejasLbl);
}
return jpanel;
}
The panel should look like a small white box with 3 labels in it, however, the labels don't show unless I set their bounds. Why does this happen? If I'm setting a FlowLayout, the labels should be positioned automatically.
This is how the panel shows:
Solved it, I had to call panel.validate() on my main frame in order to show them.

color of JButton

After reviewing many previous StackOverflow posts, I am still unable to get my JButton to be black instead of the default color. Here is what my button looks like:
And here's my code:
public void setStartButton() {
JPanel panel = this.jPanel1;
panel.setLayout(null);
JButton button = new JButton("START");
// size and location of start button
int res = java.awt.Toolkit.getDefaultToolkit().getScreenResolution();
int length = (int) Math.floor(10.0*res/25.4); // side lengths of square button
int offset = length/2; // because button should be centered...but its x and y location are given by its upper left hand corner
button.setBounds(centerX-offset, centerY-offset, length, length);
// color of start button
button.setBackground(BLACK);
button.setOpaque(true);
button.setContentAreaFilled(false);
// font
button.setFont(new Font("Arial", Font.PLAIN, 8));
button.setVisible(true);
panel.add(button);
}
By the way, when I change setContentAreaFilled to true, it makes no difference.
I know that the function is indeed being called, because the location and font info for my button is working just fine.
Any assistance would be much appreciated! Thanks!
A JButton is made of a series of layers, including the content, border and focus layers. Depending on what you're trying to do, you may need to remove all of them, for example...
public class TestPane extends JPanel {
public TestPane() {
setLayout(new GridBagLayout());
setStartButton();
}
public void setStartButton() {
JButton button = new JButton("START");
button.setMargin(new Insets(20, 20, 20, 20));
// color of start button
button.setOpaque(true);
button.setContentAreaFilled(true);
button.setBorderPainted(false);
button.setFocusPainted(false);
button.setBackground(BLACK);
button.setForeground(WHITE);
// font
button.setFont(new Font("Arial", Font.PLAIN, 8));
add(button);
}
}
I'd also strongly encourage you to consider making use of an appropriate layout manager and using the properties of it and the JButton to generate the desired padding you need, these will work together with the font metrics, which tend to be different between systems, to generate an appropriate size for the button

How can I center align a Component with SpringLayout

I am trying to create a Form in Java with Swing and I'm having difficulty with managing my layouts.
I want to have a few text fields with labels in the center of a dialog and have "save" and "close" buttons in the lower right.
Adding the buttons to the lower right of the dialog is simple, but I am not sure how to center align the text fields. I figured that, if there wasn't a center component method, then I might be able to align the field by calculating the center of the dialog window and then updating the position when the dialog is re-sized. But I am new to swing and I'm not sure how to do either (or if that is even a good idea).
How can I center align my components using the Spring Layout Manager?
public class Main {
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
MyFrame myFrame = new MyFrame();
myFrame.setVisible(true);
}
});
}
}
Here's how the frame looks:
public class MyFrame extends JFrame {
JLabel label1;
JTextField field1;
JLabel label2;
JTextField field2;
JButton saveButton;
JButton closeButton;
public MyFrame() {
initLookAndFeel();
initFrameProperties();
initContent();
initLayout();
}
private initContent() {
label1= new JLabel("Label 1");
field1= new JTextField();
label1.setLabelFor(field1);
label2= new JLabel("Label 2");
field2= new JTextField();
label2.setLabelFor(field2);
saveButton = new JButton("Save");
closeButton = new JButton("Close");
closeButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
System.exit(0);
}
});
this.add(label1);
this.add(field1);
this.add(lebel2);
this.add(field2);
this.add(saveButton);
this.add(closeButton);
}
private void initLayout() {
SpringLayout layout = new SpringLayout();
this.setLayout(layout);
}
You can center align components by adding a constraint that sets the Horizontal Center of your component to be the same as the Horizontal Center of the content pane. This will automatically update the components position when the window is re-sized.
SpringLayout layout = new SpringLayout();
// For Horizontal Alignment
layout.putConstraint(SpringLayout.HORIZONTAL_CENTER, component, 0, SpringLayout.HORIZONTAL_CENTER, contentPane);
// For Vertical Alignment
layout.putConstraint(SpringLayout.VERTICAL_CENTER, component, 0, SpringLayout.VERTICAL_CENTER, contentPane);
setLayout(layout);
SpringLayout.NORTH specifies the top edge of a component's bounding rectangle.
SpringLayout.SOUTH specifies the bottom edge of a component's bounding rectangle.
SpringLayout.EAST specifies the right edge of a component's bounding rectangle.
SpringLayout.WEST specifies the left edge of a component's bounding rectangle.
SpringLayout.BASELINE specifies the baseline of a component.
SpringLayout.HORIZONTAL_CENTER specifies the horizontal center of a component's bounding rectangle.
SpringLayout.VERTICAL_CENTER specifies the vertical center of a component's bounding rectangle.
(How to Use SpringLayout)
Use the same springLayout.putConstraint() for placing at center, as you do in the corner.

How to make JLabel consume space when not visible?

I have a program which creates 2 Panels and then places a label and two buttons in them. The label is set to invisible setVisible(false) and then the two buttons are added and the frame is packed. When i click the first button, the label is shown, setVisible(true), and the seccond one hides it again, setVisible(false). When i click each button, they move to fill the space of the label as it hides, and move again to get out of the way of the label as it is shown. I want to stop this from happening and have the buttons stay in the same place even when the label is hidden.
Here is the code:
public class MainFrame extends JFrame{
public JLabel statusLabel;
public JButton show;
public JButton hide;
public MainFrame(){
super("MagicLabel");
JPanel topPanel = new JPanel(); //Create Top Panel
statusLabel = new JLabel(""); //Init label
statusLabel.setVisible(false); //Hide label at startup
topPanel.setSize(400, 150); //Set the size of the panel, Doesn't work
topPanel.add(statusLabel); //Add label to panel
JPanel middlePanel = new JPanel(); //Create Middle Panel
show= new JButton("Show"); //Create show button
hide= new JButton("Hide"); //Create hide button
middlePanel.setSize(400, 50); //Set the size of the panel, Doesn't work
middlePanel.add(show); //Add show button
middlePanel.add(hide); //Add hide button
this.add(topPanel, "North"); //Add Top Panel to North
this.add(middlePanel, "Center"); //Add Middle Panel to Center
addActionListeners(); //void:adds action listeners to buttons
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setBounds(100, 100, 512, 400);
this.setPreferredSize(new Dimension(400,200)); //Set size of frame, Does work
this.pack();
this.setVisible(true);
}
public void animateInstall(boolean var0){ //Void to show and hide label from action listeners
statusLabel.setVisible(var0);
sendWorkingMessage("Boo!");
}
public void sendWorkingMessage(String message){ //Void to set text of label
this.statusLabel.setForeground(new Color(225, 225, 0));
this.statusLabel.setText(message);
}
void addActionListeners(){
show.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
animateInstall(true);
}
});
hide.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
animateInstall(false);
}
});
}
this.setPreferredSize(new Dimension(400,200));
this.setMinimumSize(new Dimension(400,200));
So pack() cannot interfere.
Use CardLayout. Add the JLabel and empty JPanel. Instead of seting it visible/invisible swap the cards showing the JLabel or the JPanel when necesary.
Extending JFrame is not advisable, better extend JPanel put all your components inside and then add it to a JFrame
You need to learn how to use SwingUtilities.invokeLater(): See example how your should look like
You need to learn about Layout: Tutorial
Very dumb and easy approach in your code would be:
this.statusLabel.setForeground(bgColor); //background color
this.statusLabel.setText(" "); //some number of characters
By default for you frame you are using BorderLayout. You can try to have like:
this.add(topPanel, BorderLayout.NORTH); //Add Top Panel to North
this.add(middlePanel, BorderLayout.SOUTH); //Add Middle Panel to South
rather than at center.
Or you can create an intermediate container panel for these 2 panels, or consider other layout managers like BoxLayout, etc

Categories