problem z przekazaniem tablicy do metody paintComponent

0

Mam problem z przekazaniem do metody paintComponent() tablicy z odpowiednimi wartościami.
W tej samej klasie w metodzie setData(), tablica wyświetla prawidłowe wartości.
Zaś w metodzie paintComponent() wszystkie wartości są zerowe.
Może ktoś wie co jest grane?

klasa MyPlotter:

import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;

public class MyPlotter extends JPanel{

	int width = 320;
	int height = 130;
	float widthC;
	float heightC;
	int frameSize;
        int[] data;

	public MyPlotter(int fSize){
		setSize(width,height);		
		setPreferredSize(this.getSize());
		this.frameSize = fSize;
                data = new int[fSize+1];
	} 

    public void setData(int[] intValue){
		data = intValue;
		data = Arrays.copyOf(intValue, intValue.length);

               // TUTAJ JESZCZE WSZYSTKO JEST OK
               for (int i=0; i<440; i++)
                System.out.println("setData "+data[i]);

	repaint();
}
    

   public void paintComponent (Graphics g){	
   
                // g.drawLine(...)
                // g.setColor(...)
                // etc...
        
               for (int i = 0; i< frameSize-1;i++){ 
               //PROBLEM: WARTOŚCI ZEROWE
                  System.out.println("paint() "+data[i]);
 
               // g.drawline(...);
		}
	}
}
 

Dane wprowadzone są z innej klasy MyPanel

 
import javax.swing.JPanel;

public class MyPanel extends JPanel {
		
  private MyPlotter plotter;

     public MyPanel(){
		setSize(320,210);
		plotter = new MyPlotter(440);
		add(this.plotter,0);
	}
	
     public void setData(int[] data){
        plotter.setData(data);  
    }   
}
0

Coś skopałeś w tych fragmentach, których nie zamieściłeś. Ten kod działa dobrze:

 
import javax.swing.*;
 
public class MyMain extends JFrame{
 
    private MyPlotter plotter;
    public static void main(String[] args)
    {
        new MyMain();
    }
 
    public MyMain(){
             
        plotter = new MyPlotter(440);
        int[] data = new int[440];
        for(int i=0;i<440;i++)
        {
            data[i] = i;
        }
        plotter.setData(data);
        add(plotter);
        pack();
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);       
    }
}

import java.awt.*;
import java.awt.Graphics;
import javax.swing.JPanel;
import java.util.*;
 
public class MyPlotter extends JPanel{
 
    int width = 320;
    int height = 130;
    float widthC;
    float heightC;
    int frameSize;
    int[] data;
 
    public MyPlotter(int fSize){              
        setPreferredSize(new Dimension(300,200));
        this.frameSize = fSize;
        data = new int[fSize];
    } 
 
    public void setData(int[] intValue){
        data = intValue;
        //data = Arrays.copyOf(intValue, intValue.length);
 
               // TUTAJ JESZCZE WSZYSTKO JEST OK
        for (int i=0; i<440; i++)
            System.out.println("setData "+data[i]);
 
        repaint();
    }
 
 
    public void paintComponent (Graphics g){        

 
        for (int i = 0; i< frameSize;i++){ 
               //PROBLEM: WARTOŚCI ZEROWE - NIEPRAWDA, WSZYSTKO JEST OK
            System.out.println("paint() "+data[i]);

        }
    }
}
0

obiekt **MyPanel **jest tworzony w klasie (JPanel) MainWindow która jest z kolei dodawana do JFrame w Main

fragmenty klasy MainWindow(tylko te fragmenty odnoszące się do MyPanel):

public class MainWindow extends JPanel {

private MyPanel mypanel = new MyPanel();
  
	public MainWindow(Synthesizer synth) {
	model = (SynthMain)synth;
	// jakiś kod 
	
        add(mypanel); 
}
 

Wklejam całą klasę Main, może tu gdzieś jest jakiś błąd:


import synth.AudioSelector;
import synth.midi.*;
import synth.SynthMain;
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;


public class Main extends JPanel {
    

    public Main() {
        
        SynthMain model = new SynthMain(Player.SAMPLING_RATE);
        
        Player player = new Player(model);
        AudioSelector audioSelector = new AudioSelector(player);
        MainWindow synthPanel = new MainWindow(model);
        MidiReceiver midiReceiver = new MidiReceiver(synthPanel);
        MidiSelector midiSelector = new MidiSelector(midiReceiver);
        GridBagConstraints gbc = new GridBagConstraints();

        setLayout(new GridBagLayout());
        gbc.fill = GridBagConstraints.BOTH;
        gbc.gridwidth = GridBagConstraints.REMAINDER;
        gbc.weightx = 1;
        add(audioSelector, gbc);
        add(midiSelector, gbc);
        gbc.weighty = 1;
        gbc.weighty = 0;
        add(synthPanel, gbc);
        setBorder(new EmptyBorder(6, 6, 6, 6));
    }
 
     
    public static void main(String[] args) {
        final String title = util.Constants.PRODUCT_NAME + " " + util.Constants.VERSION";
        System.out.println(title);
        final Main m = new Main();

        
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                JFrame frame = new JFrame(title);
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.getContentPane().add(m);
                frame.pack();
                frame.setVisible(true);
                frame.setLocationRelativeTo(null);
                frame.setResizable(false);
            }
        });
    }
}


 
0

Wysłałeś nie to co trzeba,

               // TUTAJ JESZCZE WSZYSTKO JEST OK
               for (int i=0; i<440; i++)
                System.out.println("setData "+data[i]);
 
        repaint();
}
  
   public void paintComponent (Graphics g){        
 
                // g.drawLine(...)
                // g.setColor(...)
                // etc...
                //błąd MUSI być gdzieś TU
               for (int i = 0; i< frameSize-1;i++){ 
               //PROBLEM: WARTOŚCI ZEROWE
                  System.out.println("paint() "+data[i]);
 
               // g.drawline(...);
                }
        }
0

Sorry, nie wklejałem całego kodu bo myślałem, że problem jest związany z przekazaniem tablicy z jednej metody do drugiej. Ale to nie to.

Jeszcze raz wrzucam właściwy (cały kod):

P_Oscilloscope to MyPanel z poprzedniego przykładu (zmieniona nazwa klasy).
I tu faktycznie, metoda main działa. Znaczy, jeśli się uruchomi P_Oscilloscope, z testowymi wartościami. pojawia się jakiś tam wykres.
Natomiast nie działa, jesli się uruchamia główną metodę main (całej aplikacji).

**P_Oscilloscope ** (dawny MyPanel)

 

import javax.swing.JFrame;
import javax.swing.JPanel;

public class P_Oscilloscope extends JPanel {
	
	private  MyPlotter plotter = new MyPlotter(440);;

        public P_Oscilloscope(){
	
        setSize(320,210);
        add(plotter);
	}
	
	public void setData(int[] data){
      plotter.setData(data);  
    }

    
    // ten main działa OK
    public static void main(String[]args){
    int[] mass =  new int[441];
    int j = 1; // jakieś testowe dane
            for (int i =0; i<441;i++) {
                if (i%2==0)j=j*(-1);
            mass[i]=i*64*j;
        }
    JFrame frame =  new JFrame();
    P_Oscilloscope mp = new P_Oscilloscope();
    frame.add(mp);
    frame.setSize(300, 300);         
    mp.setData(mass);         
    frame.setVisible(true);  
 }
    
}

MyPlotter


import java.awt.Color;
import java.awt.Graphics;
import java.util.Arrays;
import javax.swing.JPanel;


public class MyPlotter extends JPanel{

	private int width = 320;
	private int height = 130;
	private float widthC;
	private float heightC;
	private int sampleSize;
	private int frameSize;
	private  int[] toDraw;
	private float x, prevX;
	
	public MyPlotter(int fSize){
		setSize(width,height);		
		setPreferredSize(this.getSize());
		this.frameSize = fSize;
                toDraw =  new int[441];
                sampleSize = 1;
 
	} 

    
    public void setData(int[] data){
    
        toDraw = Arrays.copyOf(data, data.length);

           // to działa OK
          //for (int i =0 ;i<420; i++ )
          // System.out.println("setData "+ toDraw[i]);
      repaint();
	}
    

	
    @Override
	public void paintComponent(Graphics g){	
   
        
		widthC = ((float)width/frameSize); 			
		sampleSize = (16 == 16 ? 65536 : 256);			
		heightC = (((float)height-15)/sampleSize);			
			
		g.setColor(Color.black);			
		g.fillRect(0,0,width,height);  

		g.setColor(Color.gray);		
		for (int i = 1; i<height;i+=height/8) 
			g.drawLine(0,i,width,i);			
		for (int i = 1; i<width;i+=width/8) 
			g.drawLine(i,0,i,height);		
		   		
		g.setColor(Color.lightGray);
		g.drawLine(0,(int)(height/2),width,(int)((height/2)));
		
		  		
		g.setColor(Color.green); 		
		x = 0;	

	
		for (int i = 0; i< frameSize-1;i++){ 
           
                 // Wartości zerowe w przypadku uruchamiania całej aplikacji
                 System.out.println("paint "+toDraw[i]);
           
            
			prevX = x;
			x +=widthC;

            g.drawLine ((int)prevX,(int)((height/2+toDraw[i]*heightC)),(int)x,(int)((height/2+toDraw[i+1]*heightC))); // rysuje wykres


		}
	}
}

 
0

Wytłumacz dlaczego zamieszczasz kod który działa, a nie ten który nie działa.

0

Sęk w tym, że nie wiem gdzie jest błąd. Pewnie jakbym wiedział co jest źle, to nie zawracałbym nikomu tym głowy ;-)

Trochę przerobiłem ten program. Oprócz tych klas z mojego poprzedniego postu czyli P_Oscilloscope (który jest widokiem oscyloskopu) i MyPlotter który jest głównym oknem oscyloskopu osadzonym w P_Oscilloscope dodaję jeszcze:
MainWindow (który jest panelem z wszystkimi komponentami, ale w tym przykładzie jest dodany tylko oscyloskop), tu jest metoda main.
C_Oscilloscope (kontroler oscyloskopu), tu z warstwy modelu przychodzi sygnał (zmieniające się wartości od -32768 do +32768).
W tym przykładzie warstwa modelu jest odłączona, zatem w C_Oscilloscope do testów generuje się jakiś tam testowy sygnał.

W dalszym ciągu mam ten problem, że nie mogę z jednej metody do drugiej w tej samej klasie "przerzucić" tablicę z odpowiednimi wartościami.
Nawet po przerobieniu tablicy toDraw na statyczną, toDraw w getSignal (w C_Oscilloscope) ma zerowe wartości.

klasa C_Oscilloscope

 

import java.util.Arrays;
import java.util.Random;

public class C_Oscilloscope {

    private int frameSize = (int) (44100 / 100F);
    private int idx, numFramesToSkip = 10;
    private static int[] toDraw = new int[441];
    private static int[] data = new int[441];


    public C_Oscilloscope() {

        for (int i = 0; i < 441; i++) {
            toDraw[i] = 0;
            data[i] = 0;
        }
    }

    public void setSignal(int in) {

        // wejście z warstwy modelu wyłączone więc generuję testowy sygnał
       Random randomGenerator = new Random();
        int j = 0;
        for (int i = 0; i < 44100; i++) {
            int randomInt = randomGenerator.nextInt(32768* 2) - (32768);
            if (i % 4 == 0) {
                j = randomInt;
            }
         in = j;
        }


        if (idx++ > frameSize * numFramesToSkip) {
            idx = 0;
        } else {

            if (idx < frameSize) {
                data[idx] = in;
            }

            if (idx == frameSize) {
                // PROBLEM: tą tablicę z tymi wartościami chcę mieć w getSignal()
                toDraw = Arrays.copyOf(data, data.length);
            }

        }
    }

    public int[] getSignal() {

        
        // po odkomentowaniu PONIŻSZEGO to działa, ale gdy zakomentowane zerowe wartości
//             Random randomGenerator = new Random();
//             int j=0;
//             for (int i = 0; i < 440; i++) {
//             int randomInt = randomGenerator.nextInt(32768*2)-(32768);
//             if (i%4==0) j = randomInt;
//             toDraw[i]=j;         
//        }

        
 for (int i = 0; i < 440; i++) 
            System.out.println(toDraw[i]);

        return toDraw;
    }
}

klasa MainWindow z metodą main (powiązanie C_Oscilloscope z P_Oscilloscope)

 
import java.awt.*;
import javax.swing.*;


public class MainWindow extends JPanel {
    
     public static void main(String args[])
     throws Exception {
     SwingUtilities.invokeLater(new Runnable() {

     public void run() {
     JFrame frame = new JFrame();
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
     frame.getContentPane().add(new MainWindow());
     frame.pack();
     frame.setVisible(true);
     }
     });
     }
     

    private final P_Oscilloscope posc = new P_Oscilloscope();
    private final C_Oscilloscope cosc = new C_Oscilloscope();
  
    public MainWindow() {
        
        setPreferredSize(new Dimension(600, 300));
 
        // tutaj bardzo dużo różnych komponentów
        
        posc.setData(cosc.getSignal()); // powiązanie kondtrolera z widokiem
        add(posc);
    }

}

P_Oscilloscope i MyPlotter w moim poprzednim poście.

0

Nie analizowałem algorytmu, ale błąd masz w metodzie setSignal().

           //Program nigdy nie dochodzi do tego miejsca  
            if (idx == frameSize) {
                // PROBLEM: tą tablicę z tymi wartościami chcę mieć w getSignal()
                toDraw = Arrays.copyOf(data, data.length);
            }
0

Trochę przerobiłem ten kod i wydaje mi się, że problem leży w tym, że wykonywane są dwie instancje P_Oscilloscope, dlatego wartości zerowe.
Mam pytanie. W jaki sposób pobrać do MainWindow, który jest głównym panelem z wszystkimi komponentami instancję P_Oscilloscope utworzoną w C_Oscilloscope?
A nie tworzenie obiektu P_Oscilloscope w MainWindow? Może zastosować Singletona?

MainWindow

 
    public class MainWindow extends JPanel {
       // to chyba powoduje problem:
       private  C_Oscilloscope controler= new C_Oscilloscope();
       private  P_Oscilloscope presentation = new P_Oscilloscope(controller, 441);

    public MainWindow() 
        {
        add(presentation);
        }
    }

C_Oscilloscope po zmianach

public class C_Oscilloscope {

    private P_Oscilloscope presentation;
	
	int frameSize = 441	
	int i,numFramesToSkip = 10;
	int data;
	private int[] toDraw = new int[frameSize];
	
	public C_Oscilloscope(){

		this.presentation = new P_Oscilloscope(this,frameSize);
	}
	
	public void setSignal(int input){ // sygnał przychodzi z modelu
		
		if (i++ > frameSize*numFramesToSkip)
			i = 0; 	
		else{ 
			if ((i < frameSize)){
				toDraw[i] = input; 
			}

			if (i == frameSize){
				((P_Oscilloscope)this.presentation).setData(toDraw);
				// tutaj jest OK
			}
		}
	}
}
 

P_Oscilloscope

 
public class P_Oscilloscope extends JPanel {
	
	private  MyPlotter oscillo  = new MyPlotter(440);;

        public P_Oscilloscope(C_Oscilloscope control,int frameSize){
		setSize(320,210);
        add(this.oscillo);
	}
	
	public void setData(int[] data){
        
      // tutaj jest OK
      oscillo.setData(data);  
    }
0

W klasie MainWindow

private  P_Oscilloscope presentation = controller.getPresentation();

W klasie C_Oscilloscope dopisz metodę getPresentation().

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.