sabato 11 settembre 2010

Adding row to a JTable that uses AbstractTableModel (Java 1.6)

I'm writing a Java program that uses JTable and AbstractTableModel. As usual, I like to improvise, I like to add features following the inspiration. This time I wanted to create a table with static data, but at a certain point...hey, why not adding data dynamically? 
This way of life is funny but can create a lot of problems: I'm stubborn and I want to fix them.
"Every table object uses a table model object to manage the actual table data. A table model object must implement the TableModel interface. If the programmer does not provide a table model object, JTable automatically creates an instance of DefaultTableModel."
DefaultTableModel can easily add/remove a row, but what happens if we want to use AbstractTableModel?
I browsed the internet but I wasn't able to find a solution: people suggest to use DefaultTableModel (too easy), to call the superclass method fireTableRowsInserted(), or fireTableDataChanged() and fireTableRowsUpdated(int firstRow, int lastRow)...
These solutions don't work for me.
I found a fix experimenting a lot of ideas but the solution is quite easy: we have to pass the new data to the AbstractTableModel and call:

table.revalidate();
table.repaint();
tableModel.fireTableDataChanged();

That's all! Below a concrete example, the code I'm  using:

import java.stuff...

private JTable table;

private Object[][] newData, oldData;

MyTableModel myTableModel;

     public myClass() {

         newData = {{"Kathy", "Smith",
                     "Snowboarding", new Integer(5), new Boolean(false)},
                    {"John", "Doe",
                     "Rowing", new Integer(3), new              Boolean(true)},
                    {"Sue", "Black",
                     "Knitting", new Integer(2), new  Boolean(false)},
                    {"Jane", "White",
                     "Speed reading", new Integer(20), new Boolean(true)},
                    {"Joe", "Brown",
                     "Pool", new Integer(10), new Boolean(false)}


          myTableModel = new MyTableModel();
          myTableModel.setData(newData);

          table = new JTable(myTableModel);
          // add features to the table here
     }

     /**
      * This method adds a row to the table. We have to
      * append the new row to the existing data, pass new
      * data to AbstractTableModel
      */
      private void addRow() {
          oldData = newData;
          newData = new Object[oldData.length + 1][];

          // Copy old data to new data
          for (int x = 0; x < oldData.length; x++) { 

              newData[x] = oldData[x]; 
          } 

         // Append new row 
         newData[oldData.length] = new Object[]{new Boolean(true)}; 

         // Pass the new data to the table model
         myTableModel.setModelData(newData); 

         // Update the table 
         table.revalidate(); 
         table.repaint();

         myTableModel.fireTableDataChanged();
    } 

    class MyTableModel extends AbstractTableModel { 
       // Static column Names 
      private String[] columnNames = {"bla", "bla", "bla", 
                                      "bla", "bla"}; 
      // Data to populate the table 
      private Object[][] data; 

      public void setData(Object[][] data){ 
          this.data = data; 
      } 

      @Override 
      public int getColumnCount() { 
          return columnNames.length; 
      } 

      @Override 
      public int getRowCount() { 
          return data.length; 
      } 

      @Override 
      public String getColumnName(int col) { 
          return columnNames[col]; 
      } 

      @Override 
      public Object getValueAt(int row, int col) { 
          return data[row][col]; 
      }  

      @Override 
      public Class getColumnClass(int c) { 
          return getValueAt(0, c).getClass(); 
      }  

      @Override 
      public boolean isCellEditable(int row, int col) { 
           return true; 
      } 
      
      @Override 
      public void setValueAt(Object value, int row, int col) { 
          data[row][col] = value; 
          fireTableCellUpdated(row, col); 
      } 
    }

I apologize if blogspot doesn't format the code in the right way and I hope this solution will work for you as it does for me.

Best regards.

domenica 5 settembre 2010

40tude Dialog - Write access error

40tude Dialog worked fine on my Windows 7 x64 until today: if I run 40tude, this message box appears:

You don't have necessary write access to "C:\Program Files (x86)\40tude Dialog"

We can fix the error if we change the compatibility mode:
  1. Right click on the 40tude' shortcut or on dialog.exe
  2. Click on Properties
  3. Check the Run this program in compatibility mode for checkbox
  4. Select Windows XP (Service Pack 3) and click Apply
Now 40tude should run again (in my case this fix worked). We can quit the program and disable the compatibility mode.

Best regards.

sabato 4 settembre 2010

IR receivers (Animax)

I was looking around in an electronic and hardware store a couple of weeks ago and I saw two left IR receivers (a TSOP1730 and a TSOP1333). I knew these electronic components are quite difficult to find, at least in the town where I use to spend my holidays, so I bought them to build a couple of IR receivers to remote control an old TV card and MPlayer (and Totem, vlc, tvtime...).
I've never soldered components onto a stripboard in my life but the hardware layout is very simple and I have fun building things on my own.
Modern computers do not include RS232 serial ports anymore but in my holidays house I have this prehistoric PC with two serial ports (COM1 and COM2) so...why not?
I used the following components for the first receiver:
  1. A stripboard.
  2. Vishay Telefunken TSOP1730 (the Photo Module for PCM Remote Control Systems receiver - carrier frequency = 30 kHz).
  3. A positive voltage regulator L7805CV (output voltage of 5 V) .
  4. One female serial connector RS232.
  5. Switching diode 1N4148 (cathode --> black band).
  6. 4.7 uF Electrolytic Capacitor (cathode is the shorter pin).
  7. One 4.7K Ohm resistor (no matter what direction of assembly we'll use).
There's plenty of tutorials over the internet and I won't write the nth (obsolete) howto but a couple of things I deducted building my own receivers:


The assembly is very easy: we can insert the pieces into the stripboard and realize all of the connections between the components melting the resin cored electrical solder (because it's a conductor). The bottom of the stripboard should look like the image on the right (image taken from http://usbirboy.sourceforge.net/). We don't need to realize a professional soldering but we have to avoid to cross the connections, so a minimal project is required.

The components are very small and delicate. It's very easy to break them, so we need to insert the stripboard into something resistant. I used an old mouse to contain the stripboard (my beautiful cat jumps on my desk continually). This kind of "case" could limit the reception and the project should take it into account. My first receiver works fine with all of my remote controls: I'm using a Philips SRP4004/87 because it has dedicated buttons for DVD, VCR, TV and STB.

I'm building another, more complicated, receiver into the box of a serial connector RS232. The space is minimal and it's very hard to keep the components separated. And I don't know if the TSOP1333 will work. Anyway I'd like to build a self-made USB receiver. I will try the complete kit in the fanshop as soon as possible, assembling it should be very funny.


It's very easy to set up the remote control on Ubuntu: type these commands in a terminal:


 # The serial port is configured as COM, we have to disable it with setserial
 stefano@SERVER:~$ sudo apt-get install setserial
 # We can disable permanently the serial port as uart
 # Let's choose "manual"
 stefano@SERVER:~$ sudo dpkg-reconfigure setserial

 # We have to modify/create the file autoserial.conf
 # and insert the line /dev/ttyS0 uart none
 stefano@SERVER:~$ sudo gedit /var/lib/setserial/autoserial.conf

 # We have to copy autoserial.conf to /etc/serial.conf
 stefano@SERVER:~$ sudo cp /var/lib/setserial/autoserial.conf /etc/serial.conf

 # Now we can install Lirc
 stefano@SERVER:~$ sudo apt-get install lirc lirc-modules-source module-assistant

 # and set up it choosing "custom" for the remote control,
 # none for the transmitter and /dev/ttyS0 for the serial port
 stefano@SERVER:~$ sudo dpkg-reconfigure lirc-modules-source

 # Now we can set up the remote control
 stefano@SERVER:~$ sudo /etc/init.d/lirc stop
 stefano@SERVER:~$ sudo irrecord -f -d /dev/lirc0 lircd.conf
 stefano@SERVER:~$ sudo move lircd.conf /etc/lirc
 stefano@SERVER:~$ sudo /etc/init.d/lirc restart

My /etc/lirc/hardware.conf:


# /etc/lirc/hardware.conf
#
#Chosen Remote Control
REMOTE="Custom"
REMOTE_MODULES="lirc_dev lirc_serial"
REMOTE_DRIVER=""
REMOTE_DEVICE="/dev/lirc0"
REMOTE_SOCKET=""
REMOTE_LIRCD_CONF=""
REMOTE_LIRCD_ARGS=""

#Chosen IR Transmitter
TRANSMITTER="None"
TRANSMITTER_MODULES=""
TRANSMITTER_DRIVER=""
TRANSMITTER_DEVICE=""
TRANSMITTER_SOCKET=""
TRANSMITTER_LIRCD_CONF=""
TRANSMITTER_LIRCD_ARGS=""

#Enable lircd
START_LIRCD="true"

#Don't start lircmd even if there seems to be a good config file
#START_LIRCMD="false"

#Try to load appropriate kernel modules
LOAD_MODULES="true"

# Default configuration files for your hardware if any
LIRCMD_CONF="/etc/lirc/lircd.conf"

#Forcing noninteractive reconfiguration
#If lirc is to be reconfigured by an external application
#that doesn't have a debconf frontend available, the noninteractive
#frontend can be invoked and set to parse REMOTE and TRANSMITTER
#It will then populate all other variables without any user input
#If you would like to configure lirc via standard methods, be sure
#to leave this set to "false"
FORCE_NONINTERACTIVE_RECONFIGURATION="false"
START_LIRCMD=""

and my /etc/lirc/lircd.conf:



# Please make this file available to others
# by sending it to
#
# this config file was automatically generated
# using lirc-0.8.6(default) on Mon Aug 23 23:59:44 2010
#
# contributed by Stefano Bolli
#
# brand: Philips
# model no. of remote control: SRP4004/87
# devices being controlled by this remote:
#

begin remote

name Philips_SRP4004/87
flags RAW_CODES|CONST_LENGTH
eps 30
aeps 100

gap 107808

begin raw_codes

name KEY_TV
2749 825 501 846 469 430
505 393 1403 1294 538 358
506 393 506 393 506 390
508 391 474 427 469 430
472 425 471 427 954 396
471 425 506 844 503 395
506 393 503

name KEY_POWER
2718 858 502 844 503 395
502 397 472 875 955 390
506 395 506 393 501 423
476 423 480 393 538 359
503 398 501 396 505 393
506 393 538 361 919 426
471 878 471 455 446

name KEY_QUESTION
2717 857 506 843 504 395
538 359 1436 1260 501 398
572 320 475 430 469 428
503 395 469 431 503 395
954 391 506 843 504 395
954 393 506 843 504 393
506

name KEY_MENU
2751 825 506 843 504 393
501 395 506 844 988 359
471 430 501 395 506 393
471 428 503 395 504 395
472 425 508 393 954 841
920 876 954 846 501 395
506

name KEY_INFO
2749 825 506 843 503 394
503 396 1370 1326 469 430
503 393 504 396 505 395
501 394 508 393 503 393
506 393 506 393 503 421
480 393 987 386 478 395
504 423 476

name KEY_EXIT
2751 822 503 844 471 428
505 393 504 846 954 390
506 399 500 395 502 397
467 430 471 443 486 395
506 395 472 427 918 913
471 391 505 393 508 394
535 361 954

name KEY_LEFT
2718 860 504 866 476 398
503 393 1402 1294 472 425
542 356 508 393 472 425
503 396 471 428 505 394
471 427 954 844 919 426
505 846 952 844 537

name KEY_UP
2782 791 503 844 503 420
478 398 469 876 956 393
472 427 536 363 471 426
537 361 506 393 504 395
503 396 469 427 922 878
952 418 446 876 474 427
471 428 501

name KEY_RIGHT
2748 825 472 875 502 395
506 395 1402 1297 499 393
508 393 505 393 501 400
467 428 501 398 503 395
506 393 952 846 952 395
503 844 952 395 504

name KEY_DOWN
2748 851 514 809 469 453
478 396 469 880 917 453
446 428 471 428 469 429
504 395 504 395 471 426
503 423 478 419 928 844
920 429 501 872 512 359
922

name KEY_SELECT
2717 859 469 881 498 396
469 457 1409 1260 469 455
513 360 504 418 481 395
501 396 471 425 471 455
446 453 895 878 951 396
468 428 471 878 539 358
473

name KEY_RED
2716 860 468 876 504 420
479 395 469 878 952 397
469 430 469 428 468 430
471 428 506 393 469 430
471 425 471 455 892 433
469 878 951 419 446 880
917

name KEY_GREEN
2718 858 503 846 503 393
504 395 1403 1293 472 427
469 430 469 428 471 427
538 361 506 391 505 393
541 358 922 427 504 844
954 393 471 428 503 846
501

name KEY_YELLOW
2714 860 469 903 444 455
444 453 448 876 919 453
513 388 478 419 445 426
471 430 471 453 441 458
443 430 469 455 925 420
446 903 927 420 446 428
501 423 444

name KEY_BLUE
2714 859 469 878 504 395
499 398 1370 1352 510 361
503 396 503 398 501 395
538 362 503 395 538 358
541 361 919 428 505 391
474 876 503 395 469 428
473 425 506

name KEY_VOLUMEUP
2716 858 503 846 501 395
501 396 506 843 920 427
538 361 474 423 508 393
503 393 506 393 506 395
501 396 503 398 503 391
540 361 954 841 506 395
538 357 471 457 442

name KEY_VOLUMEDOWN
2718 859 501 844 505 393
470 429 1402 1295 471 425
503 398 504 395 501 396
471 427 469 430 469 428
471 432 469 423 508 395
915 881 503 394 473 453
960

name KEY_MUTE
2750 825 506 843 502 395
503 396 505 842 956 394
503 393 505 393 472 427
504 393 474 427 471 425
506 393 471 430 501 396
538 363 469 425 956 396
503 844 919

name KEY_BACK
2716 859 469 879 505 393
501 398 1400 1294 506 393
471 428 538 361 503 391
471 430 506 393 471 425
472 427 538 361 506 395
469 430 917 881 951 844
503

name KEY_CHANNELUP
2716 882 446 904 443 455
444 430 538 834 894 453
446 453 444 453 446 427
472 455 510 386 444 455
444 455 446 453 478 420
895 903 444 430 466 456
475 423 444 455 444

name KEY_CHANNELDOWN
2751 824 504 869 480 419
478 395 1400 1296 469 428
471 428 469 427 471 428
472 427 506 418 446 453
478 397 502 398 951 844
501 395 504 397 470 427
952

name KEY_PAGEDOWN
321

name KEY_PAGEUP
2752 827 501 846 467 430
503 395 1403 1319 476 421
480 418 481 395 469 428
471 430 467 429 471 426
471 430 469 452 481 421
441 457 927 418 515 359
503 396 535

name KEY_REWIND
2749 851 475 874 443 430
504 420 444 878 920 452
446 453 444 455 444 455
446 427 469 453 478 421
444 455 894 453 478 395
469 904 929 868 961 386
444

name KEY_PLAY
2753 825 504 843 504 420
478 396 1402 1290 505 421
480 396 501 395 504 395
504 393 505 393 506 396
951 396 503 844 951 846
501 396 954 395 504

name KEY_FASTFORWARD
2720 854 472 906 442 456
443 453 448 874 922 453
443 455 444 453 448 453
444 452 446 453 446 455
444 453 894 453 446 452
446 904 892 876 924 873
471

name KEY_STOP
2713 888 478 869 443 428
503 398 1368 1326 536 363
501 396 507 416 481 393
503 396 506 390 506 393
922 880 502 420 444 453
926 398 437 487 478 393
471

name KEY_RECORD
1886 788 993 804 991 807
989 808 991 1703 992 806
991 807 991 804 1892 1706
988 807 1887

name KEY_PAUSE
2750 825 503 844 504 393
540 358 508 842 954 393
505 391 508 391 540 359
506 393 508 391 505 393
506 393 956 842 506 393
954 841 508 391 538 360
538 361 504

name KEY_1
2750 851 443 904 446 450
481 420 1378 1289 506 420
478 421 478 421 478 418
481 420 479 418 479 420
478 423 478 418 478 421
446 451 478 423 443 456
443 453 931

name KEY_2
2752 851 446 876 471 427
506 393 469 878 918 429
471 428 471 428 503 396
503 393 506 393 540 361
502 395 471 428 471 427
504 395 471 453 478 393
506 393 956 841 472

name KEY_3
2716 859 472 875 538 361
504 395 1368 1326 501 396
505 396 572 324 504 393
540 361 505 391 506 396
470 428 503 394 505 396
505 393 470 427 471 428
956 393 501

name KEY_4
2786 789 542 805 540 359
540 356 545 804 957 391
540 358 543 354 545 356
508 389 542 356 543 359
540 356 543 356 510 389
540 358 541 358 541 356
991 807 542 356 541

name KEY_5
2750 823 471 878 499 398
503 395 1403 1317 480 396
501 395 506 418 547 324
472 432 467 429 504 393
471 428 508 391 506 392
501 423 481 393 954 844
917

name KEY_6
2712 860 503 844 471 430
503 396 503 844 919 426
473 428 503 395 472 425
469 430 505 391 474 427
506 393 538 361 503 396
468 430 502 395 506 393
921 430 504 841 501

name KEY_7
2752 823 469 903 446 455
444 453 1342 1327 471 455
444 453 448 450 446 455
444 453 444 455 443 456
446 452 444 453 446 453
444 457 444 452 895 425
540 361 472

name KEY_8
2784 791 501 846 501 398
503 393 504 871 894 428
535 363 504 393 506 420
513 361 471 451 446 427
506 393 469 430 506 393
471 428 468 428 956 842
469 455 478 395 539

name KEY_9
2719 857 502 848 501 395
504 397 1401 1294 501 395
471 428 504 390 511 393
471 425 508 394 503 395
502 395 469 432 501 393
506 395 955 841 471 430
954

name KEY_TEXT
2782 791 503 842 507 391
508 393 504 843 956 391
506 393 510 389 503 393
508 393 506 393 504 393
508 391 956 393 538 358
541 358 508 842 954 841
956

name KEY_0
2751 825 504 843 471 428
506 390 1373 1324 471 428
505 393 474 425 472 427
504 395 469 430 538 358
504 395 506 393 474 425
471 428 471 425 508 393
506 393 469 428 505

name KEY_HELP
2752 850 479 868 479 420
478 419 480 869 927 420
479 420 478 421 478 421
478 419 478 420 481 418
478 421 929 418 481 869
928 419 480 869 929 393
501

end raw_codes

end remote

I used mythbuntu-lirc-generator for initially setting up an ordinary Ubuntu system's remote control. Below a lircrc file generated by Mythbuntu Lirc Generator to control Totem.


# LIRCRC Auto Generated by Mythbuntu Lirc Generator
# Author(s): Mario Limonciello, Nick Fox, John Baab
# Created for use with Mythbuntu
begin
remote = Philips_SRP4004/87
prog = totem
button = KEY_POWER
config = quit
repeat = 0
delay = 0
end

begin
remote = Philips_SRP4004/87
prog = totem
button = KEY_MENU
config = menu
repeat = 0
delay = 0
end

begin
remote = Philips_SRP4004/87
prog = totem
button = KEY_INFO
config = show_playing
repeat = 0
delay = 0
end

begin
remote = Philips_SRP4004/87
prog = totem
button = KEY_EXIT
config = quit
repeat = 0
delay = 0
end

begin
remote = Philips_SRP4004/87
prog = totem
button = KEY_LEFT
config = left
repeat = 0
delay = 0
end

begin
remote = Philips_SRP4004/87
prog = totem
button = KEY_UP
config = up
repeat = 0
delay = 0
end

begin
remote = Philips_SRP4004/87
prog = totem
button = KEY_RIGHT
config = right
repeat = 0
delay = 0
end

begin
remote = Philips_SRP4004/87
prog = totem
button = KEY_DOWN
config = down
repeat = 0
delay = 0
end

begin
remote = Philips_SRP4004/87
prog = totem
button = KEY_VOLUMEUP
config = volume_up
repeat = 0
delay = 0
end

begin
remote = Philips_SRP4004/87
prog = totem
button = KEY_VOLUMEDOWN
config = volume_down
repeat = 0
delay = 0
end

begin
remote = Philips_SRP4004/87
prog = totem
button = KEY_MUTE
config = mute
repeat = 0
delay = 0
end

begin
remote = Philips_SRP4004/87
prog = totem
button = KEY_BACK
config = quit
repeat = 0
delay = 0
end

begin
remote = Philips_SRP4004/87
prog = totem
button = KEY_REWIND
config = seek_backward
repeat = 0
delay = 0
end

begin
remote = Philips_SRP4004/87
prog = totem
button = KEY_PLAY
config = play_pause
repeat = 0
delay = 0
end

begin
remote = Philips_SRP4004/87
prog = totem
button = KEY_FASTFORWARD
config = seek_forward
repeat = 0
delay = 0
end

begin
remote = Philips_SRP4004/87
prog = totem
button = KEY_PAUSE
config = pause
repeat = 0
delay = 0
end

begin
remote = Philips_SRP4004/87
prog = totem
button = KEY_SELECT
config = select
repeat = 0
delay = 0
end

begin
remote = Philips_SRP4004/87
prog = totem
button = KEY_STOP
config = stop
repeat = 0
delay = 0
end

begin
remote = Philips_SRP4004/87
prog = totem
button = KEY_BLUE
config = fullscreen
repeat = 0
delay = 0
end

On Windows I use Girder . WinLirc has some problem with my remote control. The latest free release of Girder (3.29b?) works fine with my Pinnacle PCTV and vlc 0.86 (we can't use the latest versions because Girder has problems with the QT libraries).

Best regards.