einfache Ampel zeichnen...



  • Danke!
    Der wxTimer funktioniert soweit. Nur beim zeichnen gibt es leider noch ein kleines Problem. Wenn ich die App starte, sieht es so aus als würde er nicht neu zeichnen->Bild 1. Manchmal blitz für eine ms etwas rotes auf, also zeichnet er doch, jedoch wird es dann sofort wieder grau. Wenn ich, während die App läuft das Fenster ständig bewege wird die Ampel angezeigt->Bild 2( wenn der Timer ausgelöst wird und die verbindung gemacht wird hängt das Fenster ganz kurz fest, danach wird dann neu gezeichnet)
    Auf den Bildern kann man auch erkennen was ich geändert habe bezüglich des Timers.

    http://img247.imageshack.us/img247/9606/test1xx5.th.jpg

    http://img146.imageshack.us/img146/9683/test2nd6.th.jpg

    Gruß
    Fabian


  • Mod

    Hm, wie sieht deine OnPaint aus?
    Evtl. solltest du nicht die Controls (statictext etc.)
    mit OnPaint Code mischen, versuch mal die Ampel in ein wxPanel
    zu zeichnen, das kannst du dann ganz normal über die Sizer einbinden.

    phlox



  • das ist meine OnPaint()

    void AuslastungFrm::OnPaint(wxPaintEvent &WXUNUSED(event))
    {
        wxPaintDC dc(this);
        if (test_data==1)
        DrawCircleRed(dc);
        if (test_data==2)
        DrawCircleYellow(dc);
        if (test_data==3)
        DrawCircleGreen(dc);
    }
    

    Ist bis auf den Timer alles das gleich wie ich zwei Beitrage weiter oben gepostet hatte...

    versuch mal die Ampel in ein wxPanel
    zu zeichnen, das kannst du dann ganz normal über die Sizer einbinden.

    Das versteh ich leider nicht 🙄
    Hab mir folgendes schon durchgelesen, aber weiter komm ich damit auch nicht.
    http://www.wxwidgets.org/manuals/2.6.3/wx_sizeroverview.html

    Gruß
    Fabian



  • Habe jetzt mal das Panel rauskommentiert, jetzt zeichnet er richitg. Ich brauch das Panel nicht unbedingt, aber später zum anzeigen der Werte wärs schon recht schön. Wie sag ich denn das er auf dem Panel zeichnen soll und nicht "darunter".
    Sorry wegen der unqualifizierten frage, aber bin halt doch noch ein anfänger 😕


  • Mod

    Hm, welches Panel?
    Ich seh da nur buttons in der CreateGUIControls,
    und wieso nutzt du keine Sizer für die Positionierung?

    Also für das Zeichnen selber würde ich eine eigene Klasse von wxPanel ableiten,
    dort die OnPaint überladen, und nach dem Status entsprechend zeichnen.
    Das Panel würdest du dann wieder in den Frame einbetten.
    Wenn der Timer im Frame aufgerufen wird, müsste dann nur das jeweilige Panel
    den neuen Statuswert erhalten.

    phlox



  • Hm, ja komisch das Panel ist oben ja wirklich nicht mit drin...

    void AuslastungFrm::CreateGUIControls(void)
    {
    	//Do not add custom code here
    	//wxDev-C++ designer will remove them.
    	//Add the custom code before or after the blocks
    	////GUI Items Creation Start
    
    	WxStatusBar1 = new wxStatusBar(this, ID_WXSTATUSBAR1);
    	WxStatusBar1->SetFieldsCount(2);
    	WxStatusBar1->SetStatusText(wxT("Netzauslastung"),0);
    	WxStatusBar1->SetStatusText(wxT(""),1);
    	int WxStatusBar1_Widths[2];
    	WxStatusBar1_Widths[0] = 100;
    	WxStatusBar1_Widths[1] = -1;
    	WxStatusBar1->SetStatusWidths(2,WxStatusBar1_Widths);
    
    	//WxPanel1 = new wxPanel(this, ID_WXPANEL1, wxPoint(0,0), wxSize(115,211), wxTRANSPARENT_WINDOW);
    	//WxPanel1->SetForegroundColour(wxColour(*wxBLACK));
    
    	//WxStaticText1 = new wxStaticText(WxPanel1, ID_WXSTATICTEXT1, wxT("Marktpreis:"), wxPoint(5,185), wxSize(56,17), 0, wxT("WxStaticText1"));
    	//WxStaticText1->Enable(false);
    
    	//WxStaticText2 = new wxStaticText(WxPanel1, ID_WXSTATICTEXT2, wxT("Kaufkraft:"), wxPoint(5,166), wxSize(50,17), 0, wxT("WxStaticText2"));
    	//WxStaticText2->Enable(false);
    
    	//Kaufkraft = new wxStaticText(WxPanel1, -1, wxT("123"), wxPoint(64,166), wxSize(22,17), 0, wxT("Kaufkraft"));
    
    	//Marktpreis = new wxStaticText(WxPanel1, -1, wxT("456"), wxPoint(64,184), wxSize(22,17), 0, wxT("Marktpreis"));
    
    	this->SetStatusBar(WxStatusBar1);
    	this->SetSize(8,8,123,264);
    	this->SetTitle(wxT("WIMAX"));
    	this->Center();
    	this->SetIcon(wxNullIcon);
    
    	////GUI Items Creation End	
    }
    

    so siehts momentan aus mit dem auskommentierten panel. wie gesagt, so zeichnet er korrekt!


  • Mod

    Wie gesagt, ersetze das Panel am besten mit einer von wxPanel abgeleiteten Klasse,
    dann müsstest du da keine Probleme mehr haben. Ist auch vom Ansatz her sauberer und leichter zu erweitern.



  • Ok, werd ich mich morgen vormittag mal mit befassen muss jetzt erstmal zur Arbeit...

    Gruß
    Fabian



  • Hallo,

    hab mich heute mal an dem neuen Panel versucht...

    Panle.h:

    class myPanel : public wxPanel
    {
    	private:
    
    	public:
    		   myPanel();
               virtual ~myPanel();
    		   void SetData(double test_Data);
    		   void OnPaint(wxPaintEvent &event);
    
    	protected:
                  void DrawCircleRed(wxDC& dc);
    		      void DrawCircleYellow(wxDC& dc);
    		      void DrawCircleGreen(wxDC& dc);
    
    };
    

    Panel.cpp

    #include "Panel.h"
    double t_data;
    
    myPanel::myPanel()
    {
    
     Create(wxWindow* parent, wxWindowID id = -1, 
     const wxPoint& pos = (0,0), const wxSize& size = (115,211), 
     long style = wxTAB_TRAVERSAL, const wxString& name = "mypanel");
    
    }
    
    myPanel::~myPanel() {}
    
    void myPanel::SetData(double test_data)
    {
    t_data=test_data;
    Refresh();     
    }
    
    void myPanel::DrawCircleRed(wxDC& dc)
    {
        dc.SetPen(*wxBLACK_PEN);
        dc.SetBrush( *wxRED_BRUSH );
        dc.DrawCircle(60, 35, 20);
    
        dc.SetPen(*wxBLACK_PEN);
        dc.SetBrush(*wxWHITE_BRUSH);
        dc.DrawCircle(60, 85, 20);
    
        dc.SetPen(*wxBLACK_PEN);
        dc.SetBrush(*wxWHITE_BRUSH);
        dc.DrawCircle(60, 135, 20);
    }
    
    void myPanel::DrawCircleYellow(wxDC& dc)
    {
        dc.SetPen(*wxBLACK_PEN);
        dc.DrawCircle(60, 35, 20);
    
        dc.SetPen(*wxBLACK_PEN);
        wxColour clr(255, 255, 0);
        wxBrush yellowBrush(clr, wxSOLID);
        dc.SetBrush(yellowBrush);
        dc.DrawCircle(60, 85, 20);
    
        dc.SetPen(*wxBLACK_PEN);
        dc.SetBrush(*wxWHITE_BRUSH);
        dc.DrawCircle(60, 135, 20);
    }
    
    void myPanel::DrawCircleGreen(wxDC& dc)
    {
        dc.SetPen(*wxBLACK_PEN);
        dc.DrawCircle(60, 35, 20);
    
        dc.SetPen(*wxBLACK_PEN);
        wxColour clr(255, 255, 0);
        dc.DrawCircle(60, 85, 20);
    
        dc.SetPen(*wxBLACK_PEN);
        dc.SetBrush( *wxGREEN_BRUSH );
        dc.DrawCircle(60, 135, 20);
    }
    
    void myPanel::OnPaint(wxPaintEvent &WXUNUSED(event))
    {
        wxPaintDC dc(this);
        if (t_data==1)
        DrawCircleRed(dc);
        if (t_data==2)
        DrawCircleYellow(dc);
        if (t_data==3)
        DrawCircleGreen(dc);
    }
    

    und in meinem Framekonstruktor wird es dann so aufgerufen:

    AuslastungFrm::AuslastungFrm(wxWindow *parent, wxWindowID id, const wxString &title, const wxPoint &position, const wxSize& size, long style)
    : wxFrame(parent, id, title, position, size, style)
    
    {
    
    	CreateGUIControls();
    
    	myPanel panel = new myPanel(); //eigens Panel Zeile44
    
    	m_timer =new wxTimer(this, TIMER_ID);
    	m_timer->Start(5000, wxTIMER_CONTINUOUS);    // 5 second interval
    
        panel.SetData(test_data);       
    
    }
    

    Das ergibt dann leider mal wieder einen Fehler den ich nicht verstehe 😞

    C:\Dev-Cpp\auslastung\AuslastungFrm.cpp In constructor AuslastungFrm::AuslastungFrm(wxWindow*, wxWindowID, const wxString&, const wxPoint&, const wxSize&, long int)': 44 C:\\Dev-Cpp\\auslastung\\AuslastungFrm.cpp conversion from \myPanel*' to non-scalar type `myPanel' requested
    C:\Dev-Cpp\auslastung\Makefile.win [Build Error] [AuslastungFrm.obj] Error 1



  • new gibt einen Zeiger zurück 😉


  • Mod

    Es lohnt sich immer den Standardkonstruktor von wxPanel auch in die abgeleiten Klassen zu übernehmen:

    myPanel(wxWindow* parent, wxWindowID id , const wxPoint& pos , const wxSize& size , long style , const wxString& name ):wxPanel(parent, id,pos,size, style,name)
    //wenn man sizer benutzt reicht ein
    myPanel(wxWindow* parent, wxWindowID id):wxPanel(parent, id)
    


  • Danke erstmal für die Hinweise!
    Haben beiden insofern geholfen,das jetzt ohne Fehler kompiliert wird, er schmeißt nur noch diese Warnung:

    30 C:\Dev-Cpp\auslastung\myPanel.h [Warning] left-hand operand of comma has no effect

    Es hat sich aber jetzt leider das ganze verhalten des Porgramms geändert 😮 . Nach dem ersten clicken auf ok im anmeldedialog wird dieser nicht mehr geschlossen, erst nach dem zweitenmal klicken verschwindet der dialog, was dann aber auch ein zweites HauptFrame nachsich zieht.
    Die Ampel wird garnichtmehr gezeichnet und auch die verbindung zum Server kommt nicht mehr zustande! Erst nachdem ich den/die Hauptframme(s) geschlossen habe holt er die Verbindungen nach! Je nachdem wieviel Zeit vergangen ist...

    Gruß
    Fabian


  • Mod

    Ähm, zeig mal den Frame Konstruktor und die myApp::OnInit.



  • Create(wxWindow* parent, wxWindowID id = -1,
     const wxPoint& pos = (0,0), const wxSize& size = (115,211),
     long style = wxTAB_TRAVERSAL, const wxString& name = "mypanel");
    

    Interessante Konstrukte entählt diese Anweisung... 😉
    Schau nochmal hin dann weißt du was er mit dieser Warnung meint.



  • Framekonstruktor:

    AuslastungFrm::AuslastungFrm(wxWindow *parent, wxWindowID id, const wxString &title, const wxPoint &position, const wxSize& size, long style)
    : wxFrame(parent, id, title, position, size, style)
    
    {
    
    	CreateGUIControls();
    
    	m_timer =new wxTimer(this, TIMER_ID);
    	m_timer->Start(5000, wxTIMER_CONTINUOUS);    // 5 second interval
    
        myPanel *panel = new myPanel( this,id=-1,wxPoint(0,0), wxSize(115,211),wxTRANSPARENT_WINDOW,"mypanel"); //eigens Panel
    	panel->SetData(test_data);   
    
    }
    

    OnInit:

    bool AuslastungFrmApp::OnInit()
    {
        anmeldungDlg* dialog = new anmeldungDlg(NULL);
    	SetTopWindow(dialog);
    	dialog->Show(true);	
    
        return true;
    }
    

    Der Frame wird dann nach click auf OK hier erzeugt:

    void anmeldungDlg::WxButton_OKClick(wxCommandEvent& event)
    {
    
    	// jetzt noch verbindung zur db aufbauen, prüfen ob user vorhanden und dann erst auslastungfrm starten
    	// wenn user nicht vorhanden/password falsch, Anmeldung_fehler und zurück 
    	//WxMessageDialog_Anmeldung_fehler->ShowModal();
    
        Destroy(); //Anmeldedialog
    	frame = new AuslastungFrm(NULL);
        frame->Show(true);
    
    }
    

    @Freak_Coder
    der entsprechende Teil sieht jetzt nicht mehr ganz so aus, habe den Konstruktor genommen den phlox81 empfohlen hat sieht man auch oben.
    Meinst du mit "Interessante Konstrukte" (0,0) und (115,211)?
    Das hab ich so gemacht weil es wxDevcpp auch so angibt wenn ich ein panel über den gui editor einfüge...

    Gruß
    Fabian


  • Mod

    Irgendwie hast du eine komische Art zu programmieren 😃 😉

    Also, in der OnInit auch den Frame erzeugen, und nicht im OnOk handler.

    bool AuslastungFrmApp::OnInit()
    {
        anmeldungDlg dialog(NULL);// für nen simplen anmeldedialog brauchst du kein new.
        SetTopWindow(dialog);
        if(dialog->ShowModal()== wxID_OK)
        {
             frame = new AuslastungFrm(NULL);
             frame->Show(true);
             return true;
        }
        return false;
    }
    

    Und du solltest dir angewöhnen Sizer für die GUI zu benutzen:

    wxFlexGridSizer* fgs = new wxFlexGridSizer(3,1,0,0);
    fgs->AddGrowableRow(0);
    fgs->AddGrowableCol(0);
    myPanel *panel = new myPanel( this,id=-1); //eigens Panel
        panel->SetData(test_data);
    fgs->Add(panel, 0, wxEXPAND|wxALL, 5);
    fgs->Add(statictext1,0,wxEXPAND|wxALL, 5);
    fgs->Add(statictext2,0,wxEXPAND|wxALL, 5);
    
    this->SetSizer(fgs);
    this->Layout();
    

    Evtl. liesst du dir mal den Artikel im C++ Magazin über wxWidgets durch.

    hm, noch eine Frage, warum ist test_data bei dir global, und nicht ein member von mypanel?

    phlox



  • Irgendwie hast du eine komische Art zu programmieren

    Danke 🕶
    Naja, wie schon paarmal gesagt, bin recht neu in c++ und habe sonst immer in java programmiert und das ist doch schon in bisschen anders.

    hm, noch eine Frage, warum ist test_data bei dir global, und nicht ein member von mypanel?

    hab ich beim erstellen vergessen wird noch geändert! Die ganze Header geschichte ist auch noch nicht so mein Ding 🤡

    Evtl. liesst du dir mal den Artikel im C++ Magazin über wxWidgets durch.

    Danke, werd ich mir morgen mal durchlesen!
    Und dann auch deine Änderungen Hinweise implementieren, weiterschauen und berichten ob es besser geworden ist...

    Danke & Gruß
    Fabian



  • Meinst du mit "Interessante Konstrukte" (0,0) und (115,211)?

    Ja...

    Das hab ich so gemacht weil es wxDevcpp auch so angibt wenn ich ein panel über den gui editor einfüge...

    Hmm, komisch wozu ??? Das bringt doch nichts.



  • @phlox81
    Bin heute mal dazu gekommen deine Änderungsvorschläge zu implementieren.

    anmeldungDlg dialog(NULL);// für nen simplen anmeldedialog brauchst du kein new.
    SetTopWindow(dialog);
    if(dialog->ShowModal()== wxID_OK)
    

    Diese Anmerkung versteh ich aber überhaupt nicht... Ich habe doch eine Klasse anmeldungDlg erstellt und um diese zu nutzen muss ich doch wohl ein Objekt erzeugen und das passiert doch mittels "new"!? oder etwa nicht.
    Ohne "new" ist´s eine statische erzeugung, nur weiß ich gerade nicht mehr wirklich den Unterschied.
    Wenn ich es nicht per new mache bekomm ich folgende Fehlermeldung:

    C:\Dev-Cpp\auslastung\AuslastungApp.cpp In member function virtual bool AuslastungFrmApp::OnInit()': 36 C:\\Dev-Cpp\\auslastung\\AuslastungApp.cpp no matching function for call toAuslastungFrmApp::SetTopWindow(anmeldungDlg&)'
    note C:\Dev-Cpp\include\wx\app.h:444 candidates are: void wxAppBase::SetTopWindow(wxWindow*)
    37 C:\Dev-Cpp\auslastung\AuslastungApp.cpp base operand of ->' has non-pointer typeanmeldungDlg'
    C:\Dev-Cpp\auslastung\Makefile.win [Build Error] [AuslastungApp.obj] Error 1

    Wenn ich (36) SetTopWindow weg lasse und (37) in dialog.showModal() umändere, frisst er auch dein Code.
    Mit "new" wird alles so Fehlerfrei kompilliert.
    Ich habe jetzt ohne "new", mit den zwei änderungen implentiert.

    Nur funktionieren tut es nicht wirklich.
    Soweit ich gelesen habe soll das hier,

    if(dialog->ShowModal()== wxID_OK)
    

    nach click auf den Ok button im Dialog true zurück geben.
    nach click auf Ok passiert aber garnichts...(meine eigene WxButton_OKClick Methode habe ich auskommentiert)
    Woher weiß das Programm den welches der OK Button ist, hab ja auch noch einen Abbrechen!?
    muss ich da irgendwie noch hiermit arbeiten:

    // Mit Connect wird der Button-Click-Event mit der Methode OnInsertText verbunden, mit button als Event Sender.
    Connect(button->GetId(),wxEVT_COMMAND_BUTTON_CLICKED,wxCommandEventHandler(MyFrame::OnInsertText));
    

    Wieder mal viele Probleme und Fragen...

    Gruß
    Fabian


  • Mod

    fub0815 schrieb:

    @phlox81
    Bin heute mal dazu gekommen deine Änderungsvorschläge zu implementieren.

    anmeldungDlg dialog(NULL);// für nen simplen anmeldedialog brauchst du kein new.
    SetTopWindow(dialog);
    if(dialog->ShowModal()== wxID_OK)
    

    Diese Anmerkung versteh ich aber überhaupt nicht... Ich habe doch eine Klasse anmeldungDlg erstellt und um diese zu nutzen muss ich doch wohl ein Objekt erzeugen und das passiert doch mittels "new"!? oder etwa nicht.
    Ohne "new" ist´s eine statische erzeugung, nur weiß ich gerade nicht mehr wirklich den Unterschied.
    Wenn ich es nicht per new mache bekomm ich folgende Fehlermeldung:

    C:\Dev-Cpp\auslastung\AuslastungApp.cpp In member function virtual bool AuslastungFrmApp::OnInit()': 36 C:\\Dev-Cpp\\auslastung\\AuslastungApp.cpp no matching function for call toAuslastungFrmApp::SetTopWindow(anmeldungDlg&)'
    note C:\Dev-Cpp\include\wx\app.h:444 candidates are: void wxAppBase::SetTopWindow(wxWindow*)
    37 C:\Dev-Cpp\auslastung\AuslastungApp.cpp base operand of ->' has non-pointer typeanmeldungDlg'
    C:\Dev-Cpp\auslastung\Makefile.win [Build Error] [AuslastungApp.obj] Error 1

    Wenn ich (36) SetTopWindow weg lasse und (37) in dialog.showModal() umändere, frisst er auch dein Code.
    Mit "new" wird alles so Fehlerfrei kompilliert.
    Ich habe jetzt ohne "new", mit den zwei änderungen implentiert.

    Gut, für jemanden der aus Java kommt, ist es sicher ungewöhnlich ein objekt ohne new anzulegen.
    Aber in C++ geht das, dieses Objekt ist dann wohl lokal, und wird beim verlassen der Funktion/des Blocks automatisch zerstört.
    Der Fehler mit SetTopWindow ist auch einfach zu erklären:
    Die Methode verlangt einen Pointer, wenn du ein objekt lokal anlegst, also ohne new, musst du
    einfach seine Adresse übergeben: SetTopWindow(&dialog)

    Bei new gilt jedoch, das für jedes new man auch ein delete braucht.
    In C++ gibt es keinen Garbagecollector.

    fub0815 schrieb:

    Nur funktionieren tut es nicht wirklich.
    Soweit ich gelesen habe soll das hier,

    if(dialog->ShowModal()== wxID_OK)
    

    nach click auf den Ok button im Dialog true zurück geben.
    nach click auf Ok passiert aber garnichts...(meine eigene WxButton_OKClick Methode habe ich auskommentiert)
    Woher weiß das Programm den welches der OK Button ist, hab ja auch noch einen Abbrechen!?
    muss ich da irgendwie noch hiermit arbeiten:

    // Mit Connect wird der Button-Click-Event mit der Methode OnInsertText verbunden, mit button als Event Sender.
    Connect(button->GetId(),wxEVT_COMMAND_BUTTON_CLICKED,wxCommandEventHandler(MyFrame::OnInsertText));
    

    Wieder mal viele Probleme und Fragen...

    Gruß
    Fabian

    Hatte nie behauptet das es auch funktionieren wird :p
    Ich arbeite nicht so häufig mit nicht Standard Dialogen in wx, von daher vergaß ich natürlich den wichtigen Teil 😉
    Also, du musst in deinem OnOk Handler noch dem Dialog sagen, das er jetzt Ok machen soll.
    Das geht mit EndModal(wxID_OK): http://wxwidgets.org/manuals/2.6.3/wx_wxdialog.html#wxdialogendmodal
    Für Cancel das gleiche.

    Es gibt auch noch die Möglichkeit, anstatt selber Buttons für dies anzulegen, dies von wxDialog machen zu lassen,
    wxDialog hat für solche Aufgaben einen eigenen Sizer:
    http://wxwidgets.org/manuals/2.6.3/wx_wxstddialogbuttonsizer.html#wxstddialogbuttonsizer
    welchen man mit einem aufruf von CreateDialogButtonSizer erzeugen kann:
    http://wxwidgets.org/manuals/2.6.3/wx_wxdialog.html#wxdialogcreatestddialogbuttonsizer

    phlox


Anmelden zum Antworten