日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

Fully Interactive JTables (aka Mouseover Edi

系統(tǒng) 2423 0

?

在學(xué)Swing的時(shí)候,因?yàn)橄雽懸粋€(gè)表格里面鑲嵌其他組建的功能。找到老外一片文章,如下:

原文: http://blog.palantirtech.com/2007/05/17/jtable-mouseover-editing/

?

-------------------------------------------------------------------------------------------------

?

May 17th, 2007 | Kevin

What sucks about JTables ? Everything, of course—but that’s a developer’s perspective. To the user, cell editing is rough around the edges: when and where to click, and how many times—it’s never perfectly clear. Cells in a table just don’t provide the mouseover feedback that regular components do. If only a JTable behaved like a bunch of components thrown into a giant GridBag or TableLayout

Mouseover Editing simulates just that. The idea is to attach a MouseListener to the JTable and call editCellAt(row, col) whenever the cursor moves over a new cell. In other words, even though only one cell in a table can be fully interactive (the editing cell) at any given time, as long as we keep moving that cell to stay underneath the user’s cursor, the whole table will appear to be fully interactive. If done correctly, this will appear to the user as though he’s interacting with a bunch of real components (rather than rendered stamps) inside a giant Grid/GridBag/TableLayout.

Most importantly, the user will get mouseover feedback about which cells are editable, and how to edit them. Checkboxes, buttons, and comboboxes (if the L&F supports it) will highlight to indicate press-ability and the cursor will turn to a text caret when hovering over cells that contain textfields. When done correctly, the effect is nearly seamless and very satisfying.

Here’s a webstart demo . Read on for the solution in code.

?

There are three parts to the Mouseover Editing solution (over and above what’s needed for typical JTable editing).

Part 1: Identical Editors and Renderers

This is important. Typically, a table will use a JLabel to render a cell and a JTextField to edit the cell. When the editor is swapped in to replace the renderer, there’s a slight flicker—the textfield might have a different background color, the text mayb be in a slightly different location, etc. This is all well and good when the user has to click or double-click to engage the editor, because the click can be perceived as granting permission to the program to do something on its own. However, a simple mouseover is a different story. Here, the look, feel, and placement of the editor should exactly match up with the look, feel, and placement of the renderer; otherwise, there will be a flicker trail every time the cursor passes through the JTable.

In order to make editors and renderers look and behave identically, (a) we need them to start out identical and (b) we need to apply the same transformations to them.

The easiest way to make an identical editor and renderer is to produce two objects from a combined EditorRenderer class. Here’s how that might work for a checkbox:

          public class CheckBoxEditorRenderer extends AbstractCellEditor implements TableCellRenderer
{
	private JCheckBox checkbox = new JCheckBox();
	public CheckBoxEditorRenderer() {
		super();
		checkbox.setFocusable(false);
	}
	public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
		if (value instanceof Boolean) {
			checkbox.setSelected((Boolean) value);
		}
		return checkbox;
	}
	public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
		if (value instanceof Boolean) {
			checkbox.setSelected((Boolean) value);
		}
		return checkbox;
	}
	public Object getCellEditorValue() {
		return checkbox.isSelected();
	}
}


        
?

Notice how CheckBoxEditorRenderer implements both the TableCellRenderer and TableCellEditor interfaces (the latter via AbstractCellEditor ).

Editors and renderers must also be subjected to the same transformations. In a subclass of JTable, say one called MouseoverJTable, use the following format for your prepareEditor() and prepareRenderer() methods:

    public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
	Component c = super.prepareRenderer(renderer, row, column);
	return prepareEditorRenderer(c, row, column);
	}
	public Component prepareEditor(TableCellEditor editor, int row, int column) {
	Component c = super.prepareEditor(editor, row, column);
	return prepareEditorRenderer(c, row, column);
	}
	private Component prepareEditorRenderer(Component stamp, int row, int column) {
//	 ...  All sorts of shenanigans can go on here.
	}
}

  
?

?

This ensures that both the editor and the renderer will go through the same decoration path.

Part 2: Two-stage editing

What we’ve presented thus far works really well for buttons and checkboxes, which are minimally interactive. With comboboxes and textfields, there’s a problem. Suppose you mouse over a cell with a combobox. First the combobox will become highlighted (if the L&F supports it) to indicate that it’s clickable; this is expected and reasonable behavior. If you click on it, the combobox flyout will appear; this is also expected and reasonable behavior. Now move your mouse just a little bit…. oh no! You accidentally moused over another cell, and the table decided to swap out the editor you were using (the combobox) and swap in a new editor. Goodbye flyout.

To make sure this doesn’t happen, we need editors with two states: temporarily engaged and fully engaged. When the cursor first moves over a cell, we call editCellAt(r, c), and plop the editor into place, temporarily engaged. This means it’s an interactive JComponent that responds to mouse events, but that it’s okay to swap it out and replace it with a new editor if the cursor changes location. Then, if the user starts interacting with the Editor in a way that requires the editor to keep around a bit of state (like the visibility of a flyout for a combobox), we say that the editor is fully engaged, and that the table isn’t allowed to swap it out until the user disengages it.

What this looks like in code:

    public interface TwoStageTableCellEditor extends TableCellEditor
{
    public boolean isFullyEngaged();
}

  
?
    public class ComboBoxEditorRenderer extends AbstractCellEditor implements TwoStageTableCellEditor, TableCellRenderer
{
    private JComboBox combobox;
    ...
    public Object getCellEditorValue() {
        return combobox.getSelectedItem();
    }
    public boolean isFullyEngaged() {
        return combobox.isPopupVisible();
    }
}


  
?

Part 3: Mouseover swapping

Here’s where it all comes together. Mouseover swapping is what your (subclass of) JTable does in order to keep track of which cell is being edited, where the cursor is, and whether to swap the editor from one cell to another. This is kind of boring, and only really makes sense in code, so here you go:

?

    // In the constructor...
// listeners for two-stage editing
this.addMouseListener(twoStageEditingListener);
this.addMouseMotionListener(twoStageEditingListener);


  

?

    // In the body of your JTable subclass...
private final FullMouseAdapter twoStageEditingListener = new FullMouseAdapter() {
    public void mouseMoved(MouseEvent e) {
        possiblySwitchEditors(e);
    }
    public void mouseEntered(MouseEvent e) {
        possiblySwitchEditors(e);
    }
    public void mouseExited(MouseEvent e) {
        possiblySwitchEditors(e);
    }
    public void mouseClicked(MouseEvent e) {
        possiblySwitchEditors(e);
    }
};
private void possiblySwitchEditors(MouseEvent e) {
    Point p = e.getPoint();
    if (p != null) {
        int row = rowAtPoint(p);
        int col = columnAtPoint(p);
        if (row != getEditingRow() || col != getEditingColumn()) {
            if (isEditing()) {
                TableCellEditor editor = getCellEditor();
                if (editor instanceof TwoStageTableCellEditor && !((TwoStageTableCellEditor)editor).isInStageTwo()) {
                    if (!editor.stopCellEditing()) {
                        editor.cancelCellEditing();
                    }
                }
            }

            if (!isEditing()) {
                if (row != -1 && isCellEditable(row, col)) {
                    editCellAt(row, col);
                }
            }
        }
    }
}


  
?

Conclusion

This solution works pretty well. There are a couple flaws (e.g. start editing a textfield and then mouseover a button—no feedback, because the text field is fully engaged), but overall it is much better than an unadorned JTable, and not too much of a burden on the developer. Be warned, though: it may wreak havoc on the focus system.

Extra credit: Is it possible to achieve a similar effect by forwarding MouseEvents through to the renderers/stamps?

Fully Interactive JTables (aka Mouseover Editing)


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 朝阳县| 荔波县| 揭东县| 阳城县| 中牟县| 光泽县| 汉寿县| 武隆县| 噶尔县| 石屏县| 蓬莱市| 大悟县| 娄底市| 大连市| 台北县| 新丰县| 昌黎县| 儋州市| 莱西市| 南投县| 深圳市| 平塘县| 乐都县| 托里县| 邵阳县| 方城县| 阿图什市| 探索| 南木林县| 淮南市| 双鸭山市| 蒙自县| 西藏| 北川| 雷州市| 奉贤区| 金塔县| 云霄县| 麻阳| 余江县| 泗水县|