0

我正在尝试在 java swing 中构建一个 Web 浏览器,在其中我通过添加JTabbedPane添加了新的选项卡选项。但是当我浏览另一个网页或网址等时,我想更新我当前的标签标题。我使用WebViewWebEngine作为 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));
        }
    });
}
4

2 回答 2

1

我更喜欢 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);
  }
}
于 2016-12-15T07:24:10.030 回答
1

您需要在 JTabbedPane 上调用setTitleAt(...)来更改选项卡的标题。

于 2016-12-13T15:04:42.870 回答