Visualizzazione post con etichetta swing. Mostra tutti i post
Visualizzazione post con etichetta swing. Mostra tutti i post

giovedì 9 giugno 2016

JMusicMan versione 5.0

Dopo il primo post su JMusicMan, adesso ho migliorato il programma sotto diversi aspetti. 

La funzione principale rimane invariata, ma adesso grazie al supporto di un'altra libreria, il programma gestisce diversi file audio.

Ecco le migliorie principali:

  • La lettura dei tag non presenta più bug; anzi è prevista la funzione "Reset tag" per creare un nuovo tag e non entrare in contrasto con tag creati precedentemente da programmi diversi (la cui compatibilità purtroppo, viene a cadere)
  • Eliminazione delle cartelle vuote e notifica nel caso ci siano cartelle contenenti esclusivamente materiale non-audio
  • Gestione delle ambiguità: se due o più file hanno lo stesso tag si presentano due casi:
    • I file hanno la stessa durata quindi probabilmente sono uguale; si chiede all'utente se eliminare i doppi o crearne una copia rinominata
    • I file hanno durata diversa: alla fine della procedura di aggiornamento viene chiesto di modificare i tag dei file audio, pena l'esclusione della libreria. Il messaggio si ripresenterà al successivo aggiornamento.
Tra le caratteristiche che tuttora sono in via di sviluppo (anzi sono già state implementate, ma la versione è beta) figurano:
  • Ricerca di canzoni nella libreria
  • Pannello laterale per visualizzare alcune informazioni
  • Vari automatismi fra cui numerazione automatica, riconoscimento traccia e riconoscimento tracce album tramite il servizio musicbrainz
  • Modifica titoli massivamente (in sviluppo)
Questo è uno screenshot della versione beta:

Panoramica

All'avvio il programma cercherà automaticamente file audio nella cartella "musica" del computer e comincia la catalogazione:

Se si sono verificati errori (ambiguità di tag o altro) allora una finestra di dialogo mostrerà le tracce "problematica" e chiederà all'utente la modifica dei tag:


L'utente può modificare le informazioni direttamente dentro il form. E' possibile selezionare anche più tracce. Titolo e numero traccia si memorizzano dinamicamente scrivendo nei relativi campi, Artista e Album invece si memorizzando premendo i tasti coi tre puntini sulla destra.

È anche possibile correggere le tracce anche quando sono taggate, sia singolarmente che massivamente (in quest'ultimo caso è possibile modificare solo Artista, Album e Immagine):

La sincronizzazione dei dispositivi

È una funzione che non ho curato molto ultimamente, ma comunque ricordo funzionava a dovere. Dopo aver impostato il dispositivo contenente il file .is_audio_player, il programma sincronizza la libreria del PC con quella del dispositivo trovando le tracce da copiare e quelle da eliminare semplicemente comparando due file XML che sono quelli che si trovano nella cartella Musica ("JMusicManLibrary.xml")

sabato 31 marzo 2012

Java: visualizzare gli elementi di una JTable come degli JCkeckBox

Se si vuole una JTable (una tabella swing di java) dove gli elementi (righe) selezionate sono visualizzate con un checkbox selezionato  e viceversa, con questo risultato:
è possibile modificare una proprietà della JTable tramite il metodo setDefaultRenderer(). Nel caso dello screenshot sopra, la tabella è divisa in un numero indeterminato di righe, e n° 6 colonne. La colonna interessata a visualizzare le celle con una checkbox è la prima, quindi il mio interesse è di modificare la colonna in questione. Per prima cosa definiamo la classe CheckBoxTableCellRenderer, ovvero una classe che eredita da JCheckBox e che si appoggià all'interfaccia JTableCellRenderer. Quest'ultima contiene solamente un metodo: getTableCellRendererComponent(), che noi definiamo a nostro piacere e che deve ritornare il componente (oggetto grafico) che vogliamo visualizzare nella casella, dunque il JCkeckBox

import javax.swing.JCheckBox;
import javax.swing.table.*;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import javax.swing.SwingConstants;
import java.awt.Component;
import java.awt.Insets;
import javax.swing.JTable;
import javax.swing.UIManager;

class CheckBoxTableCellRenderer
 extends JCheckBox
 implements TableCellRenderer {

 Border noFocusBorder;
 Border focusBorder;

 public CheckBoxTableCellRenderer() {
   super();
   setContentAreaFilled(true);  // sfondo opaco
   setBorderPainted(true);
   setHorizontalAlignment(SwingConstants.CENTER); (allineamento orizzontale centrato)
   setVerticalAlignment(SwingConstants.CENTER);   (allineamento verticale centrato)
 }

    @Override
 public Component getTableCellRendererComponent(JTable table, Object value,
                                                boolean isSelected,
                                                boolean hasFocus,
                                                int row, int column) {

   if(table == null) {
     //operazioni da fare nel caso la tabella non contenga alcun record
   }
   else { 
     if (isSelected) { //variabile locale che è vera se la riga è selezionata

         setForeground(table.getSelectionForeground());
         setBackground(table.getSelectionBackground());
     }
     else {

         setForeground(table.getForeground());
         setBackground(table.getBackground());
     }

     setEnabled(table.isEnabled());
     //questo pezzo di codice agisce sul bordo, per eliminare l'effetto "tasto"
     if (hasFocus) {
       if (focusBorder == null) {
         focusBorder = UIManager.getBorder("Table.focusCellHighlightBorder");
       }
       setBorder(focusBorder);
     }
     else {
       if (noFocusBorder == null) {
         if (focusBorder == null) {
           focusBorder = UIManager.getBorder("Table.focusCellHighlightBorder");
         }
         if (focusBorder != null) {
           Insets n = focusBorder.getBorderInsets(this);
           noFocusBorder = new EmptyBorder(n);
         }
       }
       setBorder(noFocusBorder);
     }

     //seleziona o meno il JCheckBox, in base al valore della cella (riga selezionata o meno)
     setSelected(Boolean.TRUE.equals(value));
   }
  //ritorna il JCheckBox 
   return this;
 }
}


Definita la classe CheckBoxTableCellRenderer, dobbiamo adesso adottarla nella JTable.
Supponiamo di avere una JTable di nome "table", quindi:



        TableColumnModel tcm = table.getColumnModel();
        TableColumn tc = tcm.getColumn(0); //la prima colonna è quella che ci interessa, in questo esempio
        tc.setCellRenderer(new CheckBoxTableCellRenderer());  

Fatto ciò, la prima colonna dunque apparirà come una lista di JCheckBox ordinati in verticale, proprio come nello screenshot sopra. Ma c'è ancora una cosa che manca: l'editor. Infatti se proviamo a modificare il valore di una JCheckBox (quindi il selezionare/deselezionare una riga), notiamo un'anomalia: compare la scritta "true" o "false". Perché? Perchè una JTable di default implementa una DefaultCellEditor, che mostra le celle come dei JTextBox, quindi mostra "true" o "false", in modo testo. Dunque un piccolo passaggio è doveroso:
tc.setCellEditor(new DefaultCellEditor(new JCheckBox()));
this.setCellSelectionEnabled(false);

Infatti (pace all'anima nostra), DefaultCellEditor prevede un costruttore con una JCheckBox. Mentre setCellSelectionEnabled() evita che si selezionino (con conseguente cambiamento del colore) le righe intere, infatti  a noi interessa distinguere se una riga è selezionata o meno guardando il JCheckBox.

Ricapitolando, i due passaggi fondamentali da compiere sulla colonna sono 2: modificare il suo renderer, e modificare il suo editor . Il renderer viene eseguito solamente quando la tabella viene disegnata, mentre il comportamento (editor) viene eseguito ogni qual volta modifichiamo il valore di una JCheckBox.
E' tutto.

Alberto