JTable (JTextArea) cell wrapping - swing

I want to adjust the size of a particular cell in JTable so that it should auto set itself when the size of text is greater than some size. This is how I am adding content to my table.
if(rs.next()) {
rs.beforeFirst();
Vector<String> columnNames = new Vector<String>();
columnNames.add("Tweet");
columnNames.add("Updated Time");
Vector<Vector<Object>> data = new Vector<Vector<Object>>();
while (rs.next()) {
Vector<Object> vector = new Vector<Object>();
Tweet = rs.getString(1);
vector.add(Tweet);
SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Timestamp time = rs.getTimestamp(2);
Updated_time = sdf.format(time);
vector.add(Updated_time);
data.add(vector);
}
DefaultTableModel dfm = new DefaultTableModel(data, columnNames);
JTable table = new JTable(dfm);
table.setAutoscrolls(true);
table.setShowGrid(false);
((DefaultTableCellRenderer)table.getDefaultRenderer(Object.class)).setOpaque(false);
table.setOpaque(false);

public class MyRenderer extends JTextArea implements TableCellRenderer {
private static final long serialVersionUID = 1L;
public MyRenderer() {
setLineWrap(true);
setWrapStyleWord(true);
setOpaque(true);
}
#Override
public Component getTableCellRendererComponent(
JTable table,
Object value,
boolean isSelected,
boolean hasFocus,
int row, int column
) {
// TODO Auto-generated method stub
setText(value.toString());//or something in value, like value.getNote()..
if (isSelected) {
setForeground(table.getSelectionForeground());
setBackground(table.getSelectionBackground());
} else {
setForeground(table.getForeground());
setBackground(table.getBackground());
}
setSize(table.getColumnModel().getColumn(column).getWidth(),
getPreferredSize().height);
if (table.getRowHeight(row) != getPreferredSize().height) {
table.setRowHeight(row, getPreferredSize().height);
}
return this;
}
}

JTable cell actually is showing JLabel, so for text wrapping you can apply html like:
"<html>" + "Your value" + "<br>" + "Desc"

Related

how to open specific/different Activity in the recyclerview whose data is from json using volley

I want to open new activity that is different in each recyclerview item.
I have read and I do not need an image item here : How to open a different activity on recyclerView item onclick
This is my Adapter
public class B001Adapter extends RecyclerView.Adapter {
private Context context;
private LayoutInflater inflater;
List<B001Data> udata = Collections.emptyList();
public B001Adapter(Context context, List<B001Data> data) {
this.context = context;
inflater = LayoutInflater.from(context);
this.udata = data;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = inflater.inflate(R.layout.datab001, parent, false);
MyHolder holder = new MyHolder(view);
return holder;
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
MyHolder myHolder = (MyHolder) holder;
final B001Data current = udata.get(position);
myHolder.device_name.setText(current.device_name);
myHolder.mac_address.setText(current.mac_address);
myHolder.status.setText("Status:" + String.valueOf(current.status));
}
#Override
public int getItemCount() {
return udata.size();
}
class MyHolder extends RecyclerView.ViewHolder {
TextView device_name, mac_address, status;
public MyHolder(View itemView) {
super(itemView);
context = itemView.getContext();
device_name = (TextView) itemView.findViewById(R.id.txt_device_name);
mac_address = (TextView) itemView.findViewById(R.id.txt_mac_address);
status = (TextView) itemView.findViewById(R.id.txt_status);
}
public void onClick(AdapterView<?> parent, View view, int position {
final Intent intent;
switch (getAdapterPosition()){
case 0:
intent = new Intent(context, MainActivity.class);
break;
case 1:
intent = new Intent(context, B001FacilityM.class);
break;
case 2:
intent = new Intent(context, B001HRD.class);
break;
default:
intent = new Intent(context, B001home.class);
break;
}
context.startActivity(intent);
}
}
}
I use volley to get Json data displayed on the recyclerView. Looking for your advice. Thanks
First You Should assign id to layout file (R.layout.datab001),
find out id using findViewsById in MyHolder() constructor
and then set onClickListener to layout like myHolder.layout.setOnClickListener(....);
in onBindViewHolder().
or check other answer
RecyclerView onClick

JTable unable to change cell value

I have created a method to created JTable as per below:
public void refTable(String jobNo) {
Report rp = new Report();
final String noJob = jobNo;
Map<Integer, String> jMap = rp.getReportInfo(jobNo);
Map<Integer, String> sortedMap = new TreeMap<Integer, String>(jMap);
String[] row = new String[sortedMap.size()];
Integer[] no = new Integer[sortedMap.size()];
String[] stat = new String[sortedMap.size()];
Boolean[] dev = new Boolean[sortedMap.size()];
String[] remark = new String[sortedMap.size()];
Boolean[] rem = new Boolean[sortedMap.size()];
userRemark = new String[sortedMap.size()];
tabSize = sortedMap.size();
int i = 0;
for (Integer key : sortedMap.keySet()) {
no[i] = key;
String[] val = sortedMap.get(key).split("###");
if (val[0].trim().equals("DEV")) {
stat[i] = "FAIL";
} else {
stat[i] = val[0].trim();
}
row[i] = val[1].trim();
dev[i] = false;
remark[i] = "";
//remark[i] = false;
//if(userRemark1[i]!=null)
userRemark[i] = RemarkDropDownList.userOthersReamrk;
//else
//userRemark[i] ="";
rem[i] = false;
i++;
}
DefaultTableModel model = new DefaultTableModel();
model.fireTableDataChanged();
jTable1.setModel(model);
model.addColumn("No:", no);
model.addColumn("Status:", stat);
model.addColumn("Details:", row);
model.addColumn("Non-Deviation", dev);
model.addColumn("Remarks", remark);
model.addColumn("Remove", rem);
model.addColumn("UR", userRemark);
TableColumn col1 = jTable1.getColumnModel().getColumn(0);
col1.setPreferredWidth(30);
TableColumn col2 = jTable1.getColumnModel().getColumn(1);
col2.setPreferredWidth(30);
TableColumn col3 = jTable1.getColumnModel().getColumn(2);
TextRenderer renderer = new TextRenderer();
col3.setCellRenderer(renderer);
col3.setPreferredWidth(350);
CellRenderer cellRender = new CellRenderer();
TableColumn col4 = jTable1.getColumnModel().getColumn(3);
col4.setCellEditor(jTable1.getDefaultEditor(Boolean.class));
col4.setCellRenderer(cellRender);
col4.setPreferredWidth(50);
TableButton buttonEditor = new TableButton("Button");
buttonEditor.addTableButtonListener(new TableButtonListener() {
//#Override
public void tableButtonClicked(int row, int col) {
RemarkDropDownList rmk = new RemarkDropDownList(noJob, row);
rmk.setVisible(true);
//userRemark1[row] = RemarkDropDownList.userOthersReamrk;
//String test = RemarkDropDownList.userOthersReamrk;
}
});
TableColumn col5 = jTable1.getColumnModel().getColumn(4);
col5.setCellRenderer(buttonEditor);
col5.setCellEditor(buttonEditor);
TableColumn col6 = jTable1.getColumnModel().getColumn(5);
col6.setCellEditor(jTable1.getDefaultEditor(Boolean.class));
col6.setCellRenderer(jTable1.getDefaultRenderer(Boolean.class));
col6.setPreferredWidth(50);
jTable1.setShowGrid(true);
jTable1.setGridColor(Color.BLACK);
jTable1.setAutoCreateRowSorter(true);
}
In my JTable I've created a button in column 5 like this.
TableButton buttonEditor = new TableButton("Button");
buttonEditor.addTableButtonListener(new TableButtonListener() {
//#Override
public void tableButtonClicked(int row, int col) {
RemarkDropDownList rmk = new RemarkDropDownList(noJob, row);
rmk.setVisible(true);
//userRemark1[row] = RemarkDropDownList.userOthersReamrk;
//String test = RemarkDropDownList.userOthersReamrk;
}
});
TableColumn col5 = jTable1.getColumnModel().getColumn(4);
col5.setCellRenderer(buttonEditor);
col5.setCellEditor(buttonEditor);
The button basically create a new JFrame with combobox inside it like this.
public class RemarkDropDownList extends javax.swing.JFrame {
public static String userOthersReamrk = "test";
private String userSelectedItem = "File Issue";
String jobno;
int rowNo;
public RemarkDropDownList() {
initComponents();
this.lblOthers.setVisible(false);
this.txtOthers.setVisible(false);
}
public RemarkDropDownList(String jobNo, int row) {
initComponents();
this.lblOthers.setVisible(false);
this.txtOthers.setVisible(false);
this.jobno = jobNo;
this.rowNo = row;
}
private void jComboBox1ActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
JComboBox cb = (JComboBox)evt.getSource();
userSelectedItem = (String)cb.getSelectedItem();
if(userSelectedItem.equalsIgnoreCase("others"))
{
this.lblOthers.setVisible(true);
this.txtOthers.setVisible(true);
}
else
{
this.lblOthers.setVisible(false);
this.txtOthers.setVisible(false);
}
}
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
if(userSelectedItem.equalsIgnoreCase("others"))
{
userOthersReamrk = txtOthers.getText().toString();
if(userOthersReamrk == null || userOthersReamrk.equalsIgnoreCase(""))
{
JOptionPane.showMessageDialog(null, "Please enter Remark");
}
}
else
{
userOthersReamrk = userSelectedItem;
//String [] remark = new String [1000];
///remark[rowNo] = userOthersReamrk;
ReportPanelMin rpm = new ReportPanelMin();
//rpm.userRemark1[rowNo] = remark[rowNo];
rpm.refTable(jobno);
this.setVisible(false);
}
}
}
Everything is working, but the last part. I've created a static global variable (userOthersReamrk) in RemarkDropDownList class (the new class) to hold user drop down selected value. I call the refTable function again to reload the table so i can assign the userOthersReamrk value to column no 7 like this userRemark = new String[sortedMap.size()];. When i debug, I can see the user selected value is assigned touserRemark array but its not population in the table. The column showing the default value test which i decalred in RemarkDropDownList. I know the code is so long, but i post everything to give better understanding on what im doing. What/where i need to make change so my user's selected value is shown in column 7 instead the default value.

How to create my own arrayAdapter for listView - Android [duplicate]

This question already has answers here:
BaseAdapter class wont setAdapter inside Asynctask - Android
(4 answers)
Closed 9 years ago.
I am trying to create my own arrayAdapter so I can place multiple textviews inside of a listview. I have searched everywhere and can not find a way to do it. I am new to this and not so sure how to handle it. So far I have an asynctask that gathers 3 strings in a JSON method. These strings are what I want placed in the textViews but I have no idea how to do so, here is my current code.
class loadComments extends AsyncTask<JSONObject, String, JSONObject> {
private ArrayAdapter<String> mAdapter = null;
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
}
protected JSONObject doInBackground(JSONObject... params) {
JSONObject json2 = CollectComments.collectComments(usernameforcomments, offsetNumber);
return json2;
}
#Override
protected void onPostExecute(JSONObject json2) {
try {
if (json2.getString(KEY_SUCCESS) != null) {
registerErrorMsg.setText("");
String res2 = json2.getString(KEY_SUCCESS);
if(Integer.parseInt(res2) == 1){
JSONArray commentArray = json2.getJSONArray(KEY_COMMENT);
final String comments[] = new String[commentArray.length()];
for ( int i=0; i<commentArray.length(); i++ ) {
comments[i] = commentArray.getString(i);
}
JSONArray numberArray = json2.getJSONArray(KEY_NUMBER);
String numbers[] = new String[numberArray.length()];
for ( int i=0; i<numberArray.length(); i++ ) {
numbers[i] = numberArray.getString(i);
}
JSONArray usernameArray = json2.getJSONArray(KEY_USERNAME);
String usernames[] = new String[usernameArray.length()];
for ( int i=0; i<usernameArray.length(); i++ ) {
usernames[i] = usernameArray.getString(i);
}
ArrayList<String> myList = new ArrayList<String>();
class MyClassAdapter extends ArrayAdapter<String> {
private Context context;
public MyClassAdapter(Context context, int textViewResourceId, ArrayList<String> items) {
super(context, textViewResourceId, items);
this.context = context;
}
public View getView(int position, View convertView) {
View view = convertView;
if (view == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.list_item, null);
}
String item = getItem(position);
if (item!= null) {
// My layout has only one TextView
TextView commentView = (TextView) view.findViewById(R.id.listComment);
TextView usernameView = (TextView) view.findViewById(R.id.listPostedBy);
TextView NumberView = (TextView) view.findViewById(R.id.listNumber);
// do whatever you want with your string and long
commentView.setText(comments);
NumberView.setText(numbers);
usernameView.setText(usernames);
}
return view;
}
}
}//end if key is == 1
else{
// Error in registration
registerErrorMsg.setText(json2.getString(KEY_ERROR_MSG));
}//end else
}//end if
} //end try
catch (JSONException e) {
e.printStackTrace();
}//end catch
}
}
new loadComments().execute();
This code does not work but I think I am on the right track.
Let us say, you create a class that hold your information about the comments instead of creating three related Arrays :
class Commentary
{
public String username;
public String comment;
public int commentaryIndex;
}
The BaseAdapter can take a List as a parameter whereas the ArrayAdapter wouldn't.
class MyRealAdapter extends BaseAdapter
{
private List<Commentary> comments;
public MyRealAdapter(List<Commentary> comments )
{
this.comments = comments;
}
#Override
public int getCount() {
return comments.size();
}
#Override
public Object getItem(int index) {
return comments.get(index);
}
#Override
public long getItemId(int index) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
Commentary c = (Commentary) getItem(position);
//c.username, c.comment, c.commentaryIndex
// create the view and stuff
return null;
}
}
As you can see, you again have the getView method but now you can retrieve your complete objet and not just a String.
There is a couple more method to override, but as you can see it's very simple.
You might need to pass other argument like a Context or a LayoutInflater to the constructor, but it's not mandatory.
EDIt :
JSONArray commentArray = json2.getJSONArray(KEY_COMMENT);
JSONArray numberArray = json2.getJSONArray(KEY_NUMBER);
JSONArray usernameArray = json2.getJSONArray(KEY_USERNAME);
ArrayList<Commentary> comments = new ArrayList<commentary>();
for ( int i=0; i<commentArray.length(); i++ ) {
Commentary c = new Commentary();
c.username = usernameArray.getString(i);
c.comment = commentArray.getString(i);
c.commentaryIndex = Integer.parseInt(numberArray.getString(i));
comments.add(c);
}
MyRealAdapter adapter = new MyRealAdapter(comments);

JTable row limitation

I have to limit the number of rows in a JTable. If I have 100 records I need to display 10 on the initial loading of JTable. I wish to put a button like "next", and after each click it shows another set of 10 records.
I have to limit the number of rows in a JTable. If i have 100 records i need to display 10 on the initial loading of JTable.
Use preferred size (+ an appropriate layout and layout constraint) to fix the size.
I wish to put a button like "next", and after each click it showing another set of 10 records.
Remove the scroll bar on the RHS of the scroll pane. Then use buttons instead for the effect of 'next/previous'.
Like this
FixedRowsTable.java
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;
class FixedRowsTable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
String[] columns = {"1","2","3","4","5","6","7"};
Integer[][] data = new Integer[1000][columns.length];
for (int xx=0; xx<data.length; xx++) {
for (int yy=0; yy<data[0].length; yy++) {
data[xx][yy] = new Integer((xx+1)*(yy+1));
}
}
final int rows = 11;
JPanel gui = new JPanel(new BorderLayout(3,3));
final JTable table = new JTable(
new DefaultTableModel(data, columns));
final JScrollPane scrollPane = new JScrollPane(
table,
JScrollPane.VERTICAL_SCROLLBAR_NEVER,
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
Dimension d = table.getPreferredSize();
scrollPane.setPreferredSize(
new Dimension(d.width,table.getRowHeight()*rows));
JPanel navigation = new JPanel(
new FlowLayout(FlowLayout.CENTER));
JButton next = new JButton(">");
next.addActionListener( new ActionListener(){
public void actionPerformed(ActionEvent ae) {
int height = table.getRowHeight()*(rows-1);
JScrollBar bar = scrollPane.getVerticalScrollBar();
bar.setValue( bar.getValue()+height );
}
} );
JButton previous = new JButton("<");
previous.addActionListener( new ActionListener(){
public void actionPerformed(ActionEvent ae) {
int height = table.getRowHeight()*(rows-1);
JScrollBar bar = scrollPane.getVerticalScrollBar();
bar.setValue( bar.getValue()-height );
}
} );
navigation.add(previous);
navigation.add(next);
gui.add(scrollPane, BorderLayout.CENTER);
gui.add(navigation, BorderLayout.SOUTH);
JOptionPane.showMessageDialog(null, gui);
}
});
}
}
If you use an AbstractTableModel you can display millions of records. The idea is that your model will be loading whatever records are needed for the view, on demand.
Here you have such a Model. It's not my best code, but will do :-) ...
public class SomeTableModel extends AbstractTableModel {
public SomeTableModel(ResultSet rs) {
this.rs = rs;
try {
pos = this.rs.getRow();
System.out.println(String.valueOf(pos));
} catch (SQLException ex) {
JOptionPane.showMessageDialog(null, ex);
}
}
public int getRowCount() {
int cnt = 0;
int apos = 0;
try {
apos = rs.getRow();
rs.last();
cnt = rs.getRow();
if (apos > 0)
rs.absolute(apos);
} catch (SQLException ex) {
System.out.println("getRowCount: " + ex);
}
return cnt;
}
public int getColumnCount() {
return 3;
}
public Object getValueAt(int rowIndex, int columnIndex) {
// make it jump back to pos !!
Object val = null;
Integer intVal;
try {
if (rowIndex == 0) {
pos = rs.getRow();
total = getRowCount();
}
rs.absolute(rowIndex + 1);
switch (columnIndex) {
case 0: intVal = rs.getInt(1); val = intVal; break;
case 1: val = rs.getString(2); break;
case 2: val = rs.getString(3); break;
default: val = "error";
}
rs.absolute(pos);
} catch (SQLException sqle) {
JOptionPane.showMessageDialog(null, "Trouble in model");
}
return val;
}
private ResultSet rs;
private int pos, total;
}
If you are loading the data from a database table, I think the best way to go is to limit the data coming from the database. Then apply a simple algorithm for the next and previous buttons.

Line Wrapping Cell Renderer - Java

I am having trouble implementing a custom cell renderer which will wrap message content when it extends past one line in length. The following is what I have:
public class MessageTable extends JTable
{
private static MessageTable messageTable;
private DefaultTableModel model = new DefaultTableModel();
private String[] emptyData = {};
private TreeMap<Integer, String> messages = null;
public class LineWrapCellRenderer extends JTextArea implements TableCellRenderer {
#Override
public Component getTableCellRendererComponent(
JTable table,
Object value,
boolean isSelected,
boolean hasFocus,
int row,
int column) {
this.setText((String)value);
this.setWrapStyleWord(true);
this.setLineWrap(true);
this.setBackground(Color.YELLOW);
int fontHeight = this.getFontMetrics(this.getFont()).getHeight();
int textLength = this.getText().length();
int lines = textLength / this.getColumns() +1;//+1, because we need at least 1 row.
int height = fontHeight * lines;
table.setRowHeight(row, height);
return this;
}
}
public MessageTable()
{
super();
messageTable = this;
this.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
model.addColumn("Message Number", emptyData);
model.addColumn("Message Content", emptyData);
this.setModel(model);
this.setFont(MappingView.theFont);
this.setDefaultRenderer(String.class, new LineWrapCellRenderer());
}
/**
* Set the current messages.
* #param messages
*/
public void setCurrentMessages(TreeMap<Integer, String> messages)
{
clearCurrentMessages();
this.messages = messages;
if (messages != null)
{
for (Integer key : messages.keySet())
{
String[] row = { key.toString(), messages.get(key).toString() };
model.addRow(row);
}
}
}
For some reason, the LineWrapCellRenderer is never used and the rows only ever contain one line of text.
What am I doing wrong?
Your cellrenderer is not used because the default table model returns Object.class for any column (it does not override AbstractTableModel's implementation):
public Class<?> getColumnClass(int columnIndex) {
return Object.class;
}
So either override the method yourself for the model or assign the renderer to Object.class.