如何更新新标签标题?
How to update new tab title?
我正在尝试在 java swing 中构建一个网络浏览器,我通过添加 JTabbedPane 添加了新的选项卡选项。但是我想在浏览另一个网页或网址等时更新我当前的标签标题。我使用 WebView 和 WebEngine 作为 html解析器。我尝试使用 WebEngine.getTitle()
更新标题名称,但没有成功。
这是我的构造函数:
public class Hello extends JFrame {
private JButton backButton = new JButton();
private JButton newPage;
private JButton forwardButton = new JButton();
private JFXPanel jfxPanel = new JFXPanel();
private JTextField locationTextField = new JTextField(100);
private JPanel fPane = new JPanel(new BorderLayout());
private JPanel totalPane = new JPanel(new BorderLayout());
private WebEngine engine;
JPanel buttonPanel = new JPanel(new BorderLayout());
public ArrayList<String> pageList = new ArrayList<>();
public ArrayList<String> historyList = new ArrayList<>();
static int value = 0;
static int inI = 0;
public ArrayList<String> title = new ArrayList<>();
public ArrayList<String> titleUrl = new ArrayList<>();
Hashtable<String, String> table;
History hist;
final JTabbedPane tb;
private GraphicsDevice device;
private JFrame frame;
public Hello() {
currentScene();
table = new Hashtable<>();
setResizable(true);
setTitle("Pooh");
ImageIcon img = new ImageIcon(Hello.class.getResource("/Panda-icon.png"));
setIconImage(img.getImage());
JPanel buttonPanel1 = new JPanel();
buttonPanel1.setBackground(Color.decode("#330300"));
backButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
BorderFactory.createRaisedBevelBorder();
actionBack();
System.out.println(value + " " + pageList.size() + " back");
}
});
backButton.setEnabled(true);
backButton.setBorderPainted(false);
buttonPanel1.add(backButton);
forwardButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (pageList.size() > value) {
value++;
}
System.out.println(value + "forwad");
actionForward();
}
});
forwardButton.setEnabled(true);
locationTextField.addKeyListener(new KeyAdapter() {
public void keyReleased(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
value++;
String tUrl = toURL(locationTextField.getText());
actionGo(locationTextField.getText());
}
}
});
locationTextField.setDragEnabled(true);
buttonPanel1.add(locationTextField, BorderLayout.EAST);
JPanel buttonPanel2 = new JPanel(new BorderLayout(5, 5));
buttonPanel2.setBackground(Color.decode("#330300"));
newPage = new JButton();
newPage.setIcon(new ImageIcon(Hello.class.getResource("/Plus.png")));
newPage.setPreferredSize(new Dimension(30,30));
newPage.setBorderPainted(false);
newPage.setBackground(Color.decode("#330300"));
newPage.setToolTipText("New Page");
newPage.setEnabled(true);
buttonPanel2.add(newPage,BorderLayout.CENTER);
buttonPanel.setBackground(Color.decode("#330300"));
buttonPanel.add(buttonPanel1, BorderLayout.WEST);
buttonPanel.add(buttonPanel2, BorderLayout.EAST);
JPanel lblBar = new JPanel(new BorderLayout());
lblBar.setPreferredSize(new Dimension(50,10));
JPanel jp = new JPanel();
jp.setLayout(new BorderLayout());
UIManager.put("TabbedPane.background",Color.decode("#330300"));
tb = new JTabbedPane();
tb.setUI(new CustomTabbedPaneUI());
tb.setForeground(Color.decode("#330300"));
**//creating initial tab with default name "Google" which i want to change when new urls are clicked**
tb.addTab("Google",fPane);
jp.add(new JLayer<JTabbedPane>(tb));
**//creating new tabs when button is clicked**
newPage.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
tb.addTab("New Tab",new JPanel());
**//a method which takes index of tabbed pane and returns a tabbed pane**
initTabComponent(inI+1);
inI++;
}
});
tb.setOpaque(true);
fPane.add(jfxPanel,BorderLayout.CENTER);
totalPane.add(buttonPanel, BorderLayout.NORTH);
totalPane.add(jp, BorderLayout.CENTER);
setExtendedState(JFrame.MAXIMIZED_BOTH);
setLayout(new BorderLayout());
getContentPane().add(totalPane,BorderLayout.CENTER);
getContentPane().add(lblStatus,BorderLayout.PAGE_END);
setPreferredSize(new Dimension(1024, 600));
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
}
}
这是我的 currentScene()
方法:
private void currentScene() {
Platform.runLater(new Runnable() {
@Override
public void run() {
WebView view = new WebView();
engine = view.getEngine();
engine.createPopupHandlerProperty();
engine.titleProperty().addListener(new ChangeListener<String>() {
@Override
public void changed(ObservableValue<? extends String> observable, String oldValue, final String newValue) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
Hello.this.setTitle(newValue);
if (newValue != null) {
table.put(newValue, tUrl);
title.add(newValue);
historyList.add(newValue);
pageList.add(tUrl);
}
}
});
}
});
engine.setOnStatusChanged(new EventHandler<WebEvent<String>>() {
@Override
public void handle(final WebEvent<String> event) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
lblStatus.setText(event.getData());
}
});
}
});
engine.locationProperty().addListener(new ChangeListener<String>() {
@Override
public void changed(ObservableValue<? extends String> ov, String oldValue, final String newValue) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
titleUrl.add(newValue);
locationTextField.setText(newValue);
}
});
}
});
engine.getLoadWorker().workDoneProperty().addListener(new ChangeListener<Number>() {
@Override
public void changed(ObservableValue<? extends Number> observableValue, Number oldValue, final Number newValue) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
progressBar.setValue(newValue.intValue());
}
});
}
});
engine.getLoadWorker()
.exceptionProperty()
.addListener(new ChangeListener<Throwable>() {
public void changed(ObservableValue<? extends Throwable> o, Throwable old, final Throwable value) {
if (engine.getLoadWorker().getState() == FAILED) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
JOptionPane.showMessageDialog(
fPane,
(value != null)
? engine.getLocation() + "\n" + value.getMessage()
: engine.getLocation() + "\nUnexpected error.",
"Loading error...",
JOptionPane.ERROR_MESSAGE);
}
});
}
}
});
jfxPanel.setScene(new Scene(view));
}
});
}
您需要在 JTabbedPane 上调用 setTitleAt(...) 来更改选项卡的标题。
我更喜欢 CloseableTabbedPane 。它有带有标签标题和图标的方法 addTab
你可以在这里下载https://github.com/dimensionv/closeabletabbedpane
package de.dimensionv.java.gui.swing.panels;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Rectangle;
import javax.swing.Icon;
/**
* Draws an icon representing an "X" in a box. The constructor accepts an icon, which will be placed next (right) to the
* 'X' icon drawn by this class. If no extra icon is needed, the empty default constructor can be used, or provide
* "null" as a value for the icon-object.
*
* @author mjoellnir
* @version 1.0
*/
public class CloseTabIcon implements Icon {
private int xPos;
private int yPos;
private int width = 16;
private int height = 16;
private final int offsetFrame = 2;
private final int offsetCross1 = 3;
private final int offsetCross2 = 4;
private Icon extraIcon = null;
/**
* Creates new "X" Icon.
*/
public CloseTabIcon() {
}
/**
* Creates new "X" Icon with an extra icon next to it.
*
* @param fileIcon the Icon-object to be placed next to this icon.
* @see javax.swing.Icon
*/
public CloseTabIcon(Icon fileIcon) {
extraIcon = fileIcon;
}
@Override
public void paintIcon(Component component, Graphics graphics, int x, int y) {
setXPos(x);
setYPos(y);
Color col = graphics.getColor();
graphics.setColor(Color.black);
// prepare coordinates for the frame...
int frameTop = y + offsetFrame;
int frameBottom = y + (height - offsetFrame);
int frameLeft = x + offsetFrame;
int frameRight = x + (width - offsetFrame);
// top line of rectangle-frame...
graphics.drawLine(frameLeft + 2, frameTop, frameRight - 2, frameTop);
// bottom line of rectangle-frame...
graphics.drawLine(frameLeft + 2, frameBottom, frameRight - 2, frameBottom);
// left line of rectangle-frame...
graphics.drawLine(frameLeft, frameTop + 2, frameLeft, frameBottom - 2);
// right line of rectangle-frame...
graphics.drawLine(frameRight, frameTop + 2, frameRight, frameBottom - 2);
// rounding
graphics.drawLine(frameLeft + 1, frameTop + 1, frameLeft + 1, frameTop + 1);
graphics.drawLine(frameRight - 1, frameTop + 1, frameRight - 1, frameTop + 1);
graphics.drawLine(frameLeft + 1, frameBottom - 1, frameLeft + 1, frameBottom - 1);
graphics.drawLine(frameRight - 1, frameBottom - 1, frameRight - 1, frameBottom - 1);
// prepare coordinates for the "X"
int crossTop1 = frameTop + offsetCross1;
int crossBottom1 = frameBottom - offsetCross1;
int crossTop2 = frameTop + offsetCross2;
int crossBottom2 = frameBottom - offsetCross2;
int crossRight1 = frameRight - offsetCross1;
int crossLeft1 = frameLeft + offsetCross1;
int crossRight2 = frameRight - offsetCross2;
int crossLeft2 = frameLeft + offsetCross2;
// first diagonal of "X": top left to bottom right...
graphics.drawLine(crossLeft1, crossTop1, crossRight1, crossBottom1);
graphics.drawLine(crossLeft1, crossTop2, crossRight2, crossBottom1);
graphics.drawLine(crossLeft2, crossTop1, crossRight1, crossBottom2);
// second diagonal of "X": top right to bottom left...
graphics.drawLine(crossRight1, crossTop1, crossLeft1, crossBottom1);
graphics.drawLine(crossRight1, crossTop2, crossLeft2, crossBottom1);
graphics.drawLine(crossRight2, crossTop1, crossLeft1, crossBottom2);
graphics.setColor(col);
if (extraIcon != null) {
extraIcon.paintIcon(component, graphics, x + getWidth(), y + 2);
}
}
@Override
public int getIconWidth() {
return getWidth() + (extraIcon != null ? extraIcon.getIconWidth() : 0);
}
@Override
public int getIconHeight() {
return getHeight();
}
/**
* Returns the bounding rectangle of this icon.
*
* @return the bounding rectangle of this icon.
* @see java.awt.Rectangle
*/
public Rectangle getBounds() {
return new Rectangle(getXPos(), getYPos(), getWidth(), getHeight());
}
/**
* Returns the x-coordinate of the position of this icon.
*
* @return the x-coordinate of the position of this icon.
*/
public int getXPos() {
return xPos;
}
/**
* Returns the y-coordinate of the position of this icon.
*
* @return the y-coordinate of the position of this icon.
*/
public int getYPos() {
return yPos;
}
/**
* Returns the width of this icon.
*
* @return the width of this icon.
*/
public int getWidth() {
return width;
}
/**
* Returns the height of this icon.
*
* @return the height of this icon.
*/
public int getHeight() {
return height;
}
/**
* Returns the extra-icon, which is to be displayed next to this icon. Might be null.
*
* @return the extra-icon.
*/
public Icon getExtraIcon() {
return extraIcon;
}
/**
* Sets the x-coordinate of the position of this icon.
*
* @param xPos the x-coordinate of the position of this icon.
*/
protected void setXPos(int xPos) {
this.xPos = xPos;
}
/**
* Sets the y-coordinate of the position of this icon.
*
* @param yPos the y-coordinate of the position of this icon.
*/
protected void setYPos(int yPos) {
this.yPos = yPos;
}
/**
* Sets the width of this icon.
* <p>
* This method should be called only within the constructor-methods.</p>
*
* @param width the width of this icon.
*/
protected void setWidth(int width) {
this.width = width;
}
/**
* Sets the height of this icon.
* <p>
* This method should be called only within the constructor-methods.</p>
*
* @param height the height of this icon.
*/
protected void setHeight(int height) {
this.height = height;
}
/**
* Sets the extra-icon to be displayed next to this icon.
* <p>
* This method should be called only within the constructor-methods.</p>
*
* @param extraIcon the extra icon to display.
*/
protected void setExtraIcon(Icon extraIcon) {
this.extraIcon = extraIcon;
}
}
package de.dimensionv.java.gui.swing.panels;
import java.awt.Component;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.Icon;
import javax.swing.JTabbedPane;
/**
* A JTabbedPane that can have a close-icon ('X') on each tab.
*
* <p>
* Since it is derived from JTabbedPane directly, it is used in exactly the same manner as the JTabbedPane. By default,
* it even behaves equally, i.e. it does not add the close-icon, thus disabling the closing-capabilities completely for
* a tab. To enable the closing-capabilities of a tab, add a boolean value (true) the the addTab-method-call.</p>
*
* <p>
* To have an additional extra icon on each tab (e.g. showing the file type), use the method addTab(String, Component,
* Icon) or addTab(String, Component, Icon, boolean). The first variant goes without closing-capabilities, while the
* second, if the boolean is set to true, comes with closing-capabilities.</p>
*
* <p>
* Clicking the 'X', of course, closes the tab. If you like to perform action, <b>after</b> the tab has already been
* closed, implement an event-listener to capture the ComponentRemoved-event. The removed tab can be retrieved by
* calling java.awt.event.ContainerEvent.getChild(), which is the event the listener will receive.</p>
*
* @author mjoellnir
*/
public class CloseableTabbedPane extends JTabbedPane implements MouseListener {
/**
* Creates a new instance of ClosableTabbedPane
*/
public CloseableTabbedPane() {
super();
initializeMouseListener();
}
/**
* Appends a tab without closing-capabilities, just as the standard JTabbedPane would do.
*
* @see javax.swing.JTabbedPane#addTab(String title, Component component) addTab
*/
@Override
public void addTab(String title, Component component) {
this.addTab(title, component, null, false);
}
/**
* Appends a tab with or without closing-capabilities, depending on the flag isClosable. If isClosable is true, a
* close-icon ('X') is displayed left of the title.
*
* @param title Title of this tab.
* @param component Contents of this tab.
* @param isClosable en-/disable closing-capabilities
* @see javax.swing.JTabbedPane#addTab(String title, Component component) addTab
*/
public void addTab(String title, Component component, boolean isClosable) {
this.addTab(title, component, null, isClosable);
}
/**
* Appends a tab with or without closing-capabilities, depending on the flag isClosable. If isClosable is true, a
* close-icon ('X') is displayed left of the title. If extraIcon is not null, it will be displayed between the closing
* icon (if present) and the tab's title. The extraIcon will be displayed indepently of the closing-icon.
*
* @param title Title of this tab.
* @param component Contents of this tab.
* @param extraIcon Extra icon to be displayed.
* @param isClosable en-/disable closing-capabilities
* @see javax.swing.JTabbedPane#addTab(String title, Component component) addTab
*/
public void addTab(String title, Component component, Icon extraIcon, boolean isClosable) {
if (isClosable) {
super.addTab(title, new CloseTabIcon(extraIcon), component);
} else {
if (extraIcon != null) {
super.addTab(title, extraIcon, component);
} else {
super.addTab(title, component);
}
}
}
@Override
public void mouseClicked(MouseEvent evt) {
int tabIndex = getUI().tabForCoordinate(this, evt.getX(), evt.getY());
if (tabIndex < 0) {
return;
}
Icon icon = getIconAt(tabIndex);
if ((icon == null) || !(icon instanceof CloseTabIcon)) {
// This tab is not intended to be closeable.
return;
}
Rectangle rect = ((CloseTabIcon) icon).getBounds();
if (rect.contains(evt.getX(), evt.getY())) {
//the tab is being closed
this.removeTabAt(tabIndex);
}
}
@Override
public void mouseEntered(MouseEvent evt) {
}
@Override
public void mouseExited(MouseEvent evt) {
}
@Override
public void mousePressed(MouseEvent evt) {
}
@Override
public void mouseReleased(MouseEvent evt) {
}
private void initializeMouseListener() {
addMouseListener(this);
}
}
我正在尝试在 java swing 中构建一个网络浏览器,我通过添加 JTabbedPane 添加了新的选项卡选项。但是我想在浏览另一个网页或网址等时更新我当前的标签标题。我使用 WebView 和 WebEngine 作为 html解析器。我尝试使用 WebEngine.getTitle()
更新标题名称,但没有成功。
这是我的构造函数:
public class Hello extends JFrame {
private JButton backButton = new JButton();
private JButton newPage;
private JButton forwardButton = new JButton();
private JFXPanel jfxPanel = new JFXPanel();
private JTextField locationTextField = new JTextField(100);
private JPanel fPane = new JPanel(new BorderLayout());
private JPanel totalPane = new JPanel(new BorderLayout());
private WebEngine engine;
JPanel buttonPanel = new JPanel(new BorderLayout());
public ArrayList<String> pageList = new ArrayList<>();
public ArrayList<String> historyList = new ArrayList<>();
static int value = 0;
static int inI = 0;
public ArrayList<String> title = new ArrayList<>();
public ArrayList<String> titleUrl = new ArrayList<>();
Hashtable<String, String> table;
History hist;
final JTabbedPane tb;
private GraphicsDevice device;
private JFrame frame;
public Hello() {
currentScene();
table = new Hashtable<>();
setResizable(true);
setTitle("Pooh");
ImageIcon img = new ImageIcon(Hello.class.getResource("/Panda-icon.png"));
setIconImage(img.getImage());
JPanel buttonPanel1 = new JPanel();
buttonPanel1.setBackground(Color.decode("#330300"));
backButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
BorderFactory.createRaisedBevelBorder();
actionBack();
System.out.println(value + " " + pageList.size() + " back");
}
});
backButton.setEnabled(true);
backButton.setBorderPainted(false);
buttonPanel1.add(backButton);
forwardButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (pageList.size() > value) {
value++;
}
System.out.println(value + "forwad");
actionForward();
}
});
forwardButton.setEnabled(true);
locationTextField.addKeyListener(new KeyAdapter() {
public void keyReleased(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
value++;
String tUrl = toURL(locationTextField.getText());
actionGo(locationTextField.getText());
}
}
});
locationTextField.setDragEnabled(true);
buttonPanel1.add(locationTextField, BorderLayout.EAST);
JPanel buttonPanel2 = new JPanel(new BorderLayout(5, 5));
buttonPanel2.setBackground(Color.decode("#330300"));
newPage = new JButton();
newPage.setIcon(new ImageIcon(Hello.class.getResource("/Plus.png")));
newPage.setPreferredSize(new Dimension(30,30));
newPage.setBorderPainted(false);
newPage.setBackground(Color.decode("#330300"));
newPage.setToolTipText("New Page");
newPage.setEnabled(true);
buttonPanel2.add(newPage,BorderLayout.CENTER);
buttonPanel.setBackground(Color.decode("#330300"));
buttonPanel.add(buttonPanel1, BorderLayout.WEST);
buttonPanel.add(buttonPanel2, BorderLayout.EAST);
JPanel lblBar = new JPanel(new BorderLayout());
lblBar.setPreferredSize(new Dimension(50,10));
JPanel jp = new JPanel();
jp.setLayout(new BorderLayout());
UIManager.put("TabbedPane.background",Color.decode("#330300"));
tb = new JTabbedPane();
tb.setUI(new CustomTabbedPaneUI());
tb.setForeground(Color.decode("#330300"));
**//creating initial tab with default name "Google" which i want to change when new urls are clicked**
tb.addTab("Google",fPane);
jp.add(new JLayer<JTabbedPane>(tb));
**//creating new tabs when button is clicked**
newPage.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
tb.addTab("New Tab",new JPanel());
**//a method which takes index of tabbed pane and returns a tabbed pane**
initTabComponent(inI+1);
inI++;
}
});
tb.setOpaque(true);
fPane.add(jfxPanel,BorderLayout.CENTER);
totalPane.add(buttonPanel, BorderLayout.NORTH);
totalPane.add(jp, BorderLayout.CENTER);
setExtendedState(JFrame.MAXIMIZED_BOTH);
setLayout(new BorderLayout());
getContentPane().add(totalPane,BorderLayout.CENTER);
getContentPane().add(lblStatus,BorderLayout.PAGE_END);
setPreferredSize(new Dimension(1024, 600));
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
}
}
这是我的 currentScene()
方法:
private void currentScene() {
Platform.runLater(new Runnable() {
@Override
public void run() {
WebView view = new WebView();
engine = view.getEngine();
engine.createPopupHandlerProperty();
engine.titleProperty().addListener(new ChangeListener<String>() {
@Override
public void changed(ObservableValue<? extends String> observable, String oldValue, final String newValue) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
Hello.this.setTitle(newValue);
if (newValue != null) {
table.put(newValue, tUrl);
title.add(newValue);
historyList.add(newValue);
pageList.add(tUrl);
}
}
});
}
});
engine.setOnStatusChanged(new EventHandler<WebEvent<String>>() {
@Override
public void handle(final WebEvent<String> event) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
lblStatus.setText(event.getData());
}
});
}
});
engine.locationProperty().addListener(new ChangeListener<String>() {
@Override
public void changed(ObservableValue<? extends String> ov, String oldValue, final String newValue) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
titleUrl.add(newValue);
locationTextField.setText(newValue);
}
});
}
});
engine.getLoadWorker().workDoneProperty().addListener(new ChangeListener<Number>() {
@Override
public void changed(ObservableValue<? extends Number> observableValue, Number oldValue, final Number newValue) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
progressBar.setValue(newValue.intValue());
}
});
}
});
engine.getLoadWorker()
.exceptionProperty()
.addListener(new ChangeListener<Throwable>() {
public void changed(ObservableValue<? extends Throwable> o, Throwable old, final Throwable value) {
if (engine.getLoadWorker().getState() == FAILED) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
JOptionPane.showMessageDialog(
fPane,
(value != null)
? engine.getLocation() + "\n" + value.getMessage()
: engine.getLocation() + "\nUnexpected error.",
"Loading error...",
JOptionPane.ERROR_MESSAGE);
}
});
}
}
});
jfxPanel.setScene(new Scene(view));
}
});
}
您需要在 JTabbedPane 上调用 setTitleAt(...) 来更改选项卡的标题。
我更喜欢 CloseableTabbedPane 。它有带有标签标题和图标的方法 addTab 你可以在这里下载https://github.com/dimensionv/closeabletabbedpane
package de.dimensionv.java.gui.swing.panels;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Rectangle;
import javax.swing.Icon;
/**
* Draws an icon representing an "X" in a box. The constructor accepts an icon, which will be placed next (right) to the
* 'X' icon drawn by this class. If no extra icon is needed, the empty default constructor can be used, or provide
* "null" as a value for the icon-object.
*
* @author mjoellnir
* @version 1.0
*/
public class CloseTabIcon implements Icon {
private int xPos;
private int yPos;
private int width = 16;
private int height = 16;
private final int offsetFrame = 2;
private final int offsetCross1 = 3;
private final int offsetCross2 = 4;
private Icon extraIcon = null;
/**
* Creates new "X" Icon.
*/
public CloseTabIcon() {
}
/**
* Creates new "X" Icon with an extra icon next to it.
*
* @param fileIcon the Icon-object to be placed next to this icon.
* @see javax.swing.Icon
*/
public CloseTabIcon(Icon fileIcon) {
extraIcon = fileIcon;
}
@Override
public void paintIcon(Component component, Graphics graphics, int x, int y) {
setXPos(x);
setYPos(y);
Color col = graphics.getColor();
graphics.setColor(Color.black);
// prepare coordinates for the frame...
int frameTop = y + offsetFrame;
int frameBottom = y + (height - offsetFrame);
int frameLeft = x + offsetFrame;
int frameRight = x + (width - offsetFrame);
// top line of rectangle-frame...
graphics.drawLine(frameLeft + 2, frameTop, frameRight - 2, frameTop);
// bottom line of rectangle-frame...
graphics.drawLine(frameLeft + 2, frameBottom, frameRight - 2, frameBottom);
// left line of rectangle-frame...
graphics.drawLine(frameLeft, frameTop + 2, frameLeft, frameBottom - 2);
// right line of rectangle-frame...
graphics.drawLine(frameRight, frameTop + 2, frameRight, frameBottom - 2);
// rounding
graphics.drawLine(frameLeft + 1, frameTop + 1, frameLeft + 1, frameTop + 1);
graphics.drawLine(frameRight - 1, frameTop + 1, frameRight - 1, frameTop + 1);
graphics.drawLine(frameLeft + 1, frameBottom - 1, frameLeft + 1, frameBottom - 1);
graphics.drawLine(frameRight - 1, frameBottom - 1, frameRight - 1, frameBottom - 1);
// prepare coordinates for the "X"
int crossTop1 = frameTop + offsetCross1;
int crossBottom1 = frameBottom - offsetCross1;
int crossTop2 = frameTop + offsetCross2;
int crossBottom2 = frameBottom - offsetCross2;
int crossRight1 = frameRight - offsetCross1;
int crossLeft1 = frameLeft + offsetCross1;
int crossRight2 = frameRight - offsetCross2;
int crossLeft2 = frameLeft + offsetCross2;
// first diagonal of "X": top left to bottom right...
graphics.drawLine(crossLeft1, crossTop1, crossRight1, crossBottom1);
graphics.drawLine(crossLeft1, crossTop2, crossRight2, crossBottom1);
graphics.drawLine(crossLeft2, crossTop1, crossRight1, crossBottom2);
// second diagonal of "X": top right to bottom left...
graphics.drawLine(crossRight1, crossTop1, crossLeft1, crossBottom1);
graphics.drawLine(crossRight1, crossTop2, crossLeft2, crossBottom1);
graphics.drawLine(crossRight2, crossTop1, crossLeft1, crossBottom2);
graphics.setColor(col);
if (extraIcon != null) {
extraIcon.paintIcon(component, graphics, x + getWidth(), y + 2);
}
}
@Override
public int getIconWidth() {
return getWidth() + (extraIcon != null ? extraIcon.getIconWidth() : 0);
}
@Override
public int getIconHeight() {
return getHeight();
}
/**
* Returns the bounding rectangle of this icon.
*
* @return the bounding rectangle of this icon.
* @see java.awt.Rectangle
*/
public Rectangle getBounds() {
return new Rectangle(getXPos(), getYPos(), getWidth(), getHeight());
}
/**
* Returns the x-coordinate of the position of this icon.
*
* @return the x-coordinate of the position of this icon.
*/
public int getXPos() {
return xPos;
}
/**
* Returns the y-coordinate of the position of this icon.
*
* @return the y-coordinate of the position of this icon.
*/
public int getYPos() {
return yPos;
}
/**
* Returns the width of this icon.
*
* @return the width of this icon.
*/
public int getWidth() {
return width;
}
/**
* Returns the height of this icon.
*
* @return the height of this icon.
*/
public int getHeight() {
return height;
}
/**
* Returns the extra-icon, which is to be displayed next to this icon. Might be null.
*
* @return the extra-icon.
*/
public Icon getExtraIcon() {
return extraIcon;
}
/**
* Sets the x-coordinate of the position of this icon.
*
* @param xPos the x-coordinate of the position of this icon.
*/
protected void setXPos(int xPos) {
this.xPos = xPos;
}
/**
* Sets the y-coordinate of the position of this icon.
*
* @param yPos the y-coordinate of the position of this icon.
*/
protected void setYPos(int yPos) {
this.yPos = yPos;
}
/**
* Sets the width of this icon.
* <p>
* This method should be called only within the constructor-methods.</p>
*
* @param width the width of this icon.
*/
protected void setWidth(int width) {
this.width = width;
}
/**
* Sets the height of this icon.
* <p>
* This method should be called only within the constructor-methods.</p>
*
* @param height the height of this icon.
*/
protected void setHeight(int height) {
this.height = height;
}
/**
* Sets the extra-icon to be displayed next to this icon.
* <p>
* This method should be called only within the constructor-methods.</p>
*
* @param extraIcon the extra icon to display.
*/
protected void setExtraIcon(Icon extraIcon) {
this.extraIcon = extraIcon;
}
}
package de.dimensionv.java.gui.swing.panels;
import java.awt.Component;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.Icon;
import javax.swing.JTabbedPane;
/**
* A JTabbedPane that can have a close-icon ('X') on each tab.
*
* <p>
* Since it is derived from JTabbedPane directly, it is used in exactly the same manner as the JTabbedPane. By default,
* it even behaves equally, i.e. it does not add the close-icon, thus disabling the closing-capabilities completely for
* a tab. To enable the closing-capabilities of a tab, add a boolean value (true) the the addTab-method-call.</p>
*
* <p>
* To have an additional extra icon on each tab (e.g. showing the file type), use the method addTab(String, Component,
* Icon) or addTab(String, Component, Icon, boolean). The first variant goes without closing-capabilities, while the
* second, if the boolean is set to true, comes with closing-capabilities.</p>
*
* <p>
* Clicking the 'X', of course, closes the tab. If you like to perform action, <b>after</b> the tab has already been
* closed, implement an event-listener to capture the ComponentRemoved-event. The removed tab can be retrieved by
* calling java.awt.event.ContainerEvent.getChild(), which is the event the listener will receive.</p>
*
* @author mjoellnir
*/
public class CloseableTabbedPane extends JTabbedPane implements MouseListener {
/**
* Creates a new instance of ClosableTabbedPane
*/
public CloseableTabbedPane() {
super();
initializeMouseListener();
}
/**
* Appends a tab without closing-capabilities, just as the standard JTabbedPane would do.
*
* @see javax.swing.JTabbedPane#addTab(String title, Component component) addTab
*/
@Override
public void addTab(String title, Component component) {
this.addTab(title, component, null, false);
}
/**
* Appends a tab with or without closing-capabilities, depending on the flag isClosable. If isClosable is true, a
* close-icon ('X') is displayed left of the title.
*
* @param title Title of this tab.
* @param component Contents of this tab.
* @param isClosable en-/disable closing-capabilities
* @see javax.swing.JTabbedPane#addTab(String title, Component component) addTab
*/
public void addTab(String title, Component component, boolean isClosable) {
this.addTab(title, component, null, isClosable);
}
/**
* Appends a tab with or without closing-capabilities, depending on the flag isClosable. If isClosable is true, a
* close-icon ('X') is displayed left of the title. If extraIcon is not null, it will be displayed between the closing
* icon (if present) and the tab's title. The extraIcon will be displayed indepently of the closing-icon.
*
* @param title Title of this tab.
* @param component Contents of this tab.
* @param extraIcon Extra icon to be displayed.
* @param isClosable en-/disable closing-capabilities
* @see javax.swing.JTabbedPane#addTab(String title, Component component) addTab
*/
public void addTab(String title, Component component, Icon extraIcon, boolean isClosable) {
if (isClosable) {
super.addTab(title, new CloseTabIcon(extraIcon), component);
} else {
if (extraIcon != null) {
super.addTab(title, extraIcon, component);
} else {
super.addTab(title, component);
}
}
}
@Override
public void mouseClicked(MouseEvent evt) {
int tabIndex = getUI().tabForCoordinate(this, evt.getX(), evt.getY());
if (tabIndex < 0) {
return;
}
Icon icon = getIconAt(tabIndex);
if ((icon == null) || !(icon instanceof CloseTabIcon)) {
// This tab is not intended to be closeable.
return;
}
Rectangle rect = ((CloseTabIcon) icon).getBounds();
if (rect.contains(evt.getX(), evt.getY())) {
//the tab is being closed
this.removeTabAt(tabIndex);
}
}
@Override
public void mouseEntered(MouseEvent evt) {
}
@Override
public void mouseExited(MouseEvent evt) {
}
@Override
public void mousePressed(MouseEvent evt) {
}
@Override
public void mouseReleased(MouseEvent evt) {
}
private void initializeMouseListener() {
addMouseListener(this);
}
}