Javaに関する様々な情報をご紹介します。

Javaに関する様々な情報をご紹介します。
評価

0

JTabbedPaneにボタンを重ねて表示したい

JTabbedPaneを使った画面で、タブの横にボタンを置くことは可能でしょうか?
タブの数が少なく、レイアウトに余裕がないので、タブの横にボタンを配置したいと考えています。

(等幅フォントでご覧ください)

┏━━┓┏━━┓
┃    ┃┃    ┃         このへんにボタン
┣━━┻┛    ┗━━━━━━━━━━━━┓
┃                                      ┃
┃                                      ┃
┃                                      ┃
┃                                      ┃
┃                                      ┃
┗━━━━━━━━━━━━━━━━━━━┛

5

回答

3668

閲覧

5件の回答

評価

0

JTabbedPaneのAPIでは不可能ですが、実装は可能です。
ただし、実装者のスキル、情熱、意志、コスト次第。

評価

0

fooさん

回答ありがとうございました。
コストがかけられないので、レイアウトを工夫することにします。

※実装できるんですね…
 もし余裕がでて実現できたらご報告します

評価

0

http://terai.xrea.jp/Swing/TabbedPaneWithText.html
これが参考になるかもしれません。

評価

0

>ka2さん
一概にどちらが良いとはいえませんが、レイアウトを工夫することで対応できるならば、
個人的には、その方が良いと思います。

例えば、JTabbedPaneのその区画は、TabLayoutPolicy,TabPosition, Font, ComponentOrientation, JTabbedPaneの上位コンテナのリサイズ等に影響を受けるので、考慮しなければいけないことが多くて面倒なのです。

つまり、ハードコーディングするとメンテナンスフェイズで何かが変更になる度に、正常に表示されなくなる可能性がありますし、他方、上記の要因を考慮して汎用的に実装するのはコストが結構かかるでしょう。

ハードコーディングした場合、メンテナンスにそのリスクを転嫁させることになるでしょう。

たとえば、
http://terai.xrea.jp/Swing/TabbedPaneWithText.html

http://terai.xrea.jp/Swing/TabbedPaneWithCheckBox.html
のコードは、最後のタブインデックスからタブ区画を算出していますが、JTabbedPaneが折り返しポリシーの場合やTabPositionの位置によっては、最後のタブインデックスが最も右に来るとは限らないので、最も右のxを算出するには、タブのラン区画の矩形を合算する必要があったりします。
また、ComponentOrientationによっても算出位置は変わるはずです。

>""さん
http://terai.xrea.jp/Swing/TabbedPaneWithText.html
そのサイトは、日本語のSwingの解説サイトでは、
一番捻りをきかせてて良いサイトだと思っています。
他にも良いサイトがあったら教えて下さい。

ただ、そのサイトはインスピレーションを得るには良いんですが、ハードコードな処理や汎用性がないのが、難がある印象がありますが。あと、最近の更新を見ると、ちょっとネタ切れ感が。。

評価

0

TabbedPaneWithCheckBoxから無理やりボタンを表示することはできました。クリックした時の見た目とか変ですが今回はここまでで。(レイアウト対応の予定です)

fooさん
""さん
ありがとうございました

(以下、テストコード)
package example;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.WindowConstants;
import javax.swing.border.Border;

public class MainPanel extends JPanel {
    private final JTabbedPane tab  = new JTabbedPane();
    private final JButton button    = new JButton("Try");
    private final JComponent panel = new JLabel("詳細設定パネル");

    public MainPanel() {
        super(new BorderLayout());
        tab.setBorder(new TabbedPaneWithCompBorder(button, tab));
        tab.addTab("設定", new JLabel("設定パネル"));

           button.addActionListener(new ActionListener() {
               public void actionPerformed(ActionEvent e){
                   if(button.getText()=="Try"){
                    tab.addTab("詳細設定", panel);
                          button.setText("押した");
                   }else{
                    tab.remove(panel);
                          button.setText("Try");
                   }
               }
           });
        add(tab, BorderLayout.CENTER);
        setPreferredSize(new Dimension(320, 100));
    }
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
    public static void createAndShowGUI() {
        try{
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        }catch(Exception e) {
            throw new InternalError(e.toString());
        }
        final int mw = 256;
        final int mh = 80;
        final JFrame frame = new JFrame("TabbedPaneWithButton");
        frame.addComponentListener(new ComponentAdapter() {
            public void componentResized(ComponentEvent e) {
                int fw = frame.getSize().width;
                int fh = frame.getSize().height;
                frame.setSize((mw>fw)?mw:fw, (mh>fh)?mh:fh);
            }
        });
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.getContentPane().add(new MainPanel());
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}

class TabbedPaneWithCompBorder implements Border, MouseListener, SwingConstants {
    private final JButton cbutton;
    private final JTabbedPane tab;
    private final JComponent dummy = new JPanel();;
    private Rectangle rect;

    public TabbedPaneWithCompBorder(JButton cbutton, JTabbedPane tab) {
        this.cbutton = cbutton;
        this.tab  = tab;
        tab.addMouseListener(this);
        cbutton.setFocusPainted(false);
        cbutton.addMouseListener(new MouseAdapter() {
            public void mouseClicked(MouseEvent me) {
                JButton cb = (JButton)me.getSource();
                cb.doClick();
            }
        });
    }
    public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
        Dimension size = cbutton.getPreferredSize();
        int xx = tab.getSize().width - size.width;
        Rectangle lastTab = tab.getUI().getTabBounds(tab, tab.getTabCount()-1);
        int tabEnd = lastTab.x + lastTab.width;
        if(xx<tabEnd) xx = tabEnd;
        rect = new Rectangle(xx, -2, size.width, size.height);
        SwingUtilities.paintComponent(g, cbutton, dummy, rect);
    }
    public Insets getBorderInsets(Component c) {
        return new Insets(0,0,0,0);
    }
    public boolean isBorderOpaque() {
        return true;
    }
    private void dispatchEvent(MouseEvent me) {
        if(rect==null || !rect.contains(me.getX(), me.getY())) return;
        Point pt = me.getPoint();
        pt.translate(0, 0);
        cbutton.setBounds(rect);
        cbutton.dispatchEvent(new MouseEvent(cbutton, me.getID()
                                          , me.getWhen(), me.getModifiers()
                                          , pt.x, pt.y, me.getClickCount()
                                          , me.isPopupTrigger(), me.getButton()));
    }

    public void mouseClicked(MouseEvent me) {
        dispatchEvent(me);
    }
    public void mouseEntered(MouseEvent me) {
        dispatchEvent(me);
    }
    public void mouseExited(MouseEvent me) {
        dispatchEvent(me);
    }
    public void mousePressed(MouseEvent me) {
        dispatchEvent(me);
    }
    public void mouseReleased(MouseEvent me) {
        dispatchEvent(me);
    }
}

質問から6ヶ月以上経過しているので、回答を書き込むことはできません。