为什么我不能用鼠标取消选择/选择JTable布尔字段,如果我使用键盘进入字段,我总是可以用空格键取消选择/选择。但在鼠标上,它有时起作用,有时不起作用。
更复杂的是,is_compilitation布尔字段的基础数据为true/false,但所有其他基础字段的基础数据为1/0,is_compilitation字段似乎总是正常工作,但其他字段是零星的。
试着注释出不同的代码,但运气不佳。我在这里发布了JTable和TableModel子类。
import com.jthink.songkong.text.TextLabel;
import javax.swing.*;
import javax.swing.table.TableCellRenderer;
import java.awt.*;
import java.awt.datatransfer.*;
import java.awt.event.*;
import java.io.IOException;
import java.util.ArrayList;
public class EditSongsTable extends JTable
{
public EditSongsTable()
{
//Disable F2 key for editing and replace with Enter character.
getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(java.awt.event.
KeyEvent.VK_F2, 0), "none");
getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(java.awt.event.
KeyEvent.VK_ENTER, 0), "startEditing");
//Changes Editor for Strings
setDefaultEditor(Object.class, new TextFieldCellEditor());
CopyAction copy = new CopyAction(this);
PasteAction paste = new PasteAction(this);
//Add Copy/Paste Popup Menu
final JPopupMenu pm = new JPopupMenu();
pm.add(copy);
pm.add(paste);
//Replace default table actions with our copy/paste actions
getActionMap().put("copy", copy);
getActionMap().put("paste", paste);
addMouseListener(new MouseAdapter()
{
@Override
public void mouseClicked(MouseEvent e)
{
if (e.isPopupTrigger())
{
highlightCells(e);
doPopup(e);
}
}
@Override
public void mouseReleased(MouseEvent e)
{
if (e.isPopupTrigger())
{
highlightCells(e);
doPopup(e);
}
}
protected void doPopup(MouseEvent e)
{
pm.show(e.getComponent(), e.getX(), e.getY());
}
/**
* Highlight cell if nothing selected
*
* @param e
*/
protected void highlightCells(MouseEvent e)
{
JTable table = (JTable) e.getSource();
if(table.getSelectedRows().length==0 || table.getSelectedColumns().length==0)
{
Point point = e.getPoint();
int row = table.rowAtPoint(point);
int col = table.columnAtPoint(point);
table.setRowSelectionInterval(row, row);
table.setColumnSelectionInterval(col, col);
}
}
});
}
/**
* RowNo column needs a different renderer from default
*
* @param row
* @param column
* @return the row label renderer
*/
@Override
public TableCellRenderer getCellRenderer(int row, int column)
{
if (column == 0)
{
return TableRowLabelRenderer.getInstanceOf();
}
else
{
return super.getCellRenderer(row, column);
}
}
class CopyAction extends AbstractAction
{
private JTable table;
public CopyAction(JTable table)
{
this.table = table;
putValue(NAME, TextLabel.COPYBUTTON.getMsg());
putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_C, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
}
@Override
public void actionPerformed(ActionEvent e)
{
Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
java.util.List<Object> data = new ArrayList<>();
final int[] rows = getSelectedRows();
for (int row : rows)
{
final int[] cols = getSelectedColumns();
for (int col : cols)
{
data.add(table.getValueAt(row, col));
}
}
cb.setContents(new CellTransferable(data), null);
}
}
class PasteAction extends AbstractAction
{
private JTable table;
public PasteAction(JTable tbl)
{
putValue(NAME, TextLabel.PASTEBUTTON.getMsg());
putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_V, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
table = tbl;
final Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
cb.addFlavorListener(new FlavorListener()
{
@Override
public void flavorsChanged(FlavorEvent e)
{
setEnabled(cb.isDataFlavorAvailable(CellTransferable.CELL_DATA_FLAVOR)
|| cb.isDataFlavorAvailable(DataFlavor.stringFlavor));
}
});
setEnabled(cb.isDataFlavorAvailable(CellTransferable.CELL_DATA_FLAVOR)
|| cb.isDataFlavorAvailable(DataFlavor.stringFlavor));
}
@Override
public void actionPerformed(ActionEvent e)
{
Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
if (cb.isDataFlavorAvailable(CellTransferable.CELL_DATA_FLAVOR))
{
try
{
int i =0;
java.util.List<Object> values = (java.util.List<Object>) cb.getData(CellTransferable.CELL_DATA_FLAVOR);
final int[] rows = getSelectedRows();
for (int row : rows)
{
final int[] cols = getSelectedColumns();
for (int col : cols)
{
if(i>=values.size())
{
i=0;
}
if(table.getColumnClass(col)==Boolean.class)
{
if(values.get(i) instanceof Boolean)
{
table.setValueAt(values.get(i), row, col);
i++;
}
}
else
{
if(values.get(i) instanceof Boolean)
{
table.setValueAt(((Boolean)values.get(i)).toString(), row, col);
}
else
{
table.setValueAt(values.get(i), row, col);
}
i++;
}
}
}
}
catch (UnsupportedFlavorException | IOException ex)
{
ex.printStackTrace();
}
}
else if(cb.isDataFlavorAvailable(DataFlavor.stringFlavor))
{
try
{
String data = (String)cb.getData(DataFlavor.stringFlavor);
final int[] rows = getSelectedRows();
for (int row : rows)
{
final int[] cols = getSelectedColumns();
for (int col : cols)
{
table.setValueAt(data, row, col);
}
}
}
catch (UnsupportedFlavorException | IOException ex)
{
ex.printStackTrace();
}
}
}
}
public static class CellTransferable implements Transferable
{
public static final DataFlavor CELL_DATA_FLAVOR = new DataFlavor(Object.class, "application/x-cell-value");
private Object cellValue;
public CellTransferable(Object cellValue)
{
this.cellValue = cellValue;
}
@Override
public DataFlavor[] getTransferDataFlavors()
{
return new DataFlavor[]{CELL_DATA_FLAVOR};
}
@Override
public boolean isDataFlavorSupported(DataFlavor flavor)
{
return CELL_DATA_FLAVOR.equals(flavor);
}
@Override
public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException
{
if (!isDataFlavorSupported(flavor))
{
throw new UnsupportedFlavorException(flavor);
}
return cellValue;
}
}
}
表格模型
import com.google.common.collect.ArrayTable;
import com.google.common.collect.Table;
import com.jthink.songkong.text.SongFieldDataType;
import com.jthink.songkong.text.SongFieldName;
import com.jthink.songlayer.Song;
import com.jthink.songlayer.SongFieldKey;
import javax.swing.table.DefaultTableModel;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.Vector;
import static com.jthink.songkong.analyse.toplevelanalyzer.EditSongsController.EDIT_MULTI_VALUE;
/**
* Edit Songs table model
*
*/
public class EditSongsTableModel extends DefaultTableModel
{
private Table<Song, SongFieldName, String> edits = null;
private List<SongFieldName> fields;
private List<Song> songs;
public EditSongsTableModel(Set<SongFieldName> fields, List<Song> songs)
{
super(songs.size(), fields.size());
this.fields= new ArrayList<>(fields);
this.songs=songs;
edits = ArrayTable.create(songs, fields);
for(Song song:songs)
{
song.setNewFilename(song.getFilename());
}
Vector<String> columnNames = new Vector<>();
columnNames.add("#");
for (SongFieldName next : fields)
{
columnNames.add(next.getName());
}
this.setColumnIdentifiers(columnNames);
}
/**
* Get the value relating this table field, making adjustments for certain fields for display
*
* @param row
* @param column
* @return
*/
public Object getValueAt(int row, int column)
{
if(column==0)
{
return String.valueOf(row + 1);
}
else
{
SongFieldName sfn = fields.get(column -1);
Song song = songs.get(row);
if(sfn.getSongFieldKey()== SongFieldKey.FILENAME)
{
return song.getNewFilename();
}
else if (sfn.getDataType() == SongFieldDataType.BOOLEAN)
{
if(sfn==SongFieldName.IS_COMPILATION)
{
return Boolean.valueOf(song.getFieldValueOrEmptyString(sfn.getSongFieldKey()));
}
else
{
if(song.getFieldValueOrEmptyString(sfn.getSongFieldKey()).equals("1"))
{
return Boolean.TRUE;
}
else
{
return Boolean.FALSE;
}
}
}
else
{
return song.getFieldValueTripleSemiColonSeparatedOrEmptyString(sfn.getSongFieldKey());
}
}
}
@Override
public void setValueAt(Object val, int row, int column)
{
SongFieldName sfn = fields.get(column - 1);
Song song = songs.get(row);
if(edits.get(song,sfn)==null)
{
//Save Original Value
edits.put(song, sfn, song.getFieldValueOrEmptyString(sfn.getSongFieldKey()));
}
if(sfn.getSongFieldKey()== SongFieldKey.FILENAME)
{
song.setNewFilename((String) val);
}
else if(sfn.getDataType()== SongFieldDataType.BOOLEAN)
{
if(sfn==SongFieldName.IS_COMPILATION)
{
song.setField(sfn.getSongFieldKey(), ((Boolean) val).toString());
}
else
{
if(val==Boolean.TRUE)
{
song.setField(sfn.getSongFieldKey(), "1");
}
else
{
song.setField(sfn.getSongFieldKey(), "0");
}
}
}
else
{
song.setField(sfn.getSongFieldKey(),
((String) val).replace(EDIT_MULTI_VALUE, "\0"));
}
fireTableCellUpdated(row, column);
}
public Class getColumnClass(int columnIndex)
{
if(columnIndex == 0)
{
return String.class;
}
else
{
SongFieldName sfn = fields.get(columnIndex - 1);
if (sfn.getDataType() == SongFieldDataType.BOOLEAN)
{
return Boolean.class;
}
else
{
return super.getColumnClass((columnIndex));
}
}
}
/**
* Cannot Edit table Row Header
*
* @param rowIndex
* @param columnIndex
* @return
*/
public boolean isCellEditable(int rowIndex, int columnIndex)
{
return columnIndex > 0;
}
/**
* Reset to original data
*
* @return
*/
public boolean reset()
{
for(Table.Cell<Song, SongFieldName, String> cell:edits.cellSet())
{
if(cell.getValue()!=null)
{
SongFieldName sfn = cell.getColumnKey();
if(sfn.getSongFieldKey()== SongFieldKey.FILENAME)
{
cell.getRowKey().setNewFilename(cell.getValue());
}
else
{
cell.getRowKey().setField(cell.getColumnKey().getSongFieldKey(), cell.getValue());
}
}
}
fireTableDataChanged();
return true;
}
}
TextFieldCelleDitor
import javax.swing.*;
import javax.swing.text.Caret;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.util.EventObject;
/**
* For String fields typing in keybaord when field has focus causes current value to be removed and editing to start
* immediatley
*
*/
public class TextFieldCellEditor extends DefaultCellEditor
{
private EventObject event;
public TextFieldCellEditor()
{
super(new JTextField());
}
public final Component getTableCellEditorComponent(final JTable table, final Object val,
final boolean isSelected,
final int row, final int column)
{
//If entered field using keyboard clear the current value
final JTextField editField = (JTextField) super.getTableCellEditorComponent(table,
val,
isSelected,
row,
column);
if (event instanceof KeyEvent)
{
final Caret caret = editField.getCaret();
caret.setDot(0);
editField.setText("");
}
return editField;
}
public boolean isCellEditable(EventObject anEvent)
{
event = anEvent;
return super.isCellEditable(anEvent);
}
}
该问题是由于使用了https://tips4java.wordpress.com/2008/11/10/table-columnadjuster/中的TableColumnAdjuster代码造成的,该代码通常用作
TableColumnAdjuster tca = new TableColumnAdjuster(table);
tca.adjustColumns();
我无法弄清楚TableColumnAdjorster的实际问题是什么,但最后我从它提取了一些代码,并为它添加了一个JTable的抽象子类,然后针对我的用例进行了扩展。我只需要它来设置合理的起始列宽度,我还调整来设置preferredSize而不是一些特定列的size。
这已经解决了这个问题,我现在可以用鼠标可靠地禁用/启用复选框了。
public class CorrectlySizedTable extends JTable
{
public void adjustColumns()
{
TableColumnModel tcm = getColumnModel();
for (int i = 0; i < tcm.getColumnCount(); i++)
{
adjustColumn(i);
}
}
public void adjustColumn(final int column)
{
TableColumn tableColumn = getColumnModel().getColumn(column);
if (! tableColumn.getResizable()) return;
int columnHeaderWidth = getColumnHeaderWidth( column );
int columnDataWidth = getColumnDataWidth( column );
int preferredWidth = Math.max(columnHeaderWidth, columnDataWidth);
updateTableColumn(column, preferredWidth);
}
/*
* Calculated the width based on the column name
*/
private int getColumnHeaderWidth(int column)
{
TableColumn tableColumn = getColumnModel().getColumn(column);
Object value = tableColumn.getHeaderValue();
TableCellRenderer renderer = tableColumn.getHeaderRenderer();
if (renderer == null)
{
renderer = getTableHeader().getDefaultRenderer();
}
Component c = renderer.getTableCellRendererComponent(this, value, false, false, -1, column);
return c.getPreferredSize().width;
}
/*
* Calculate the width based on the widest cell renderer for the
* given column.
*/
private int getColumnDataWidth(int column)
{
int preferredWidth = 0;
int maxWidth = getColumnModel().getColumn(column).getMaxWidth();
for (int row = 0; row < getRowCount(); row++)
{
preferredWidth = Math.max(preferredWidth, getCellDataWidth(row, column));
// We've exceeded the maximum width, no need to check other rows
if (preferredWidth >= maxWidth)
break;
}
return preferredWidth;
}
/*
* Get the preferred width for the specified cell
*/
private int getCellDataWidth(int row, int column)
{
// Inovke the renderer for the cell to calculate the preferred width
TableCellRenderer cellRenderer = getCellRenderer(row, column);
Component c = prepareRenderer(cellRenderer, row, column);
int width = c.getPreferredSize().width + getIntercellSpacing().width;
return width;
}
private void updateTableColumn(int column, int width)
{
final TableColumn tableColumn = getColumnModel().getColumn(column);
MainWindow.logger.severe("ColumnWidth:"+width);
tableColumn.setPreferredWidth(width);
if(column==0 || getColumnClass(column)==Boolean.class)
{
tableColumn.setMaxWidth(width);
}
}
public void setModel(TableModel dataModel) {
super.setModel(dataModel);
adjustColumns();
}
}
本文向大家介绍RadioButton实现选择后可取消选择,包括了RadioButton实现选择后可取消选择的使用技巧和注意事项,需要的朋友参考一下 Radiobutton是一种单选按钮,是由于RadioGroup管理下的一组按钮,所以一旦其中的一个button选中,再点击,就不能取消,想要取消调用Radiobutton的setchecked(boolean isChecked)的方法。 在网上找了
目前正在使用React Native,并尝试使用React Native nfc ios和React national nfc,以便我可以在ios和Android之间进行跨设备通信。我发现他们无法沟通,但我认为这是由于一个更广泛的问题(因为其他现有的应用程序也无法工作)。 如果我在iPhone7上下载NFC阅读器应用程序,在Android上下载NFC写入器应用程序,它们就无法通信。这是为什么呢?
如果你曾经使用过构建工具,你可能会对遇到的问题感到很沮丧,构建工具不是应该自动帮你完成项目的构建吗?你不得不向性能、扩展性等妥协。 比如你在构建一个项目的发布版本时,你要把一个文件拷贝到指定的位置,你在项目的元数据那里添加了版本的描述,如果版本号匹配一个特定的数字时,就把文件从A拷贝到B处。如果你依赖XML来构建,你要实现这个任务就像噩梦一样,你只能通过非标准的机制来添加一些脚本到构建中,结果就是
来源:https://github.com/atom-china/manual 这个世界上有那么多种编辑器,为什么你要花时间学习和使用 Atom 呢? 虽然 Sublime 和 TextMate 之类的编辑器已经非常好用了,但它们仅提供了很有限的拓展性。而在另一个极端,Emacs 和 Vim 提供了灵活的拓展性,但它们并不是很友好,需要使用专用的编程语言来配置和拓展。 我们觉得我们可以做得更好。我
为什么选择 NuxtJS
Nginx 是一个高性能的 Web 和反向代理服务器, 它具有有很多非常优越的特性: 作为 Web 服务器:相比 Apache,Nginx 使用更少的资源,支持更多的并发连接,体现更高的效率,这点使 Nginx 尤其受到虚拟主机提供商的欢迎。能够支持高达 50,000 个并发连接数的响应,感谢 Nginx 为我们选择了 epoll and kqueue 作为开发模型. 作为负载均衡服务器:Ngin