wxGrid Zellen und Zahlen eingabe
-
Hallo ,
hab wieder einmal eine Frage im Zusammenhang mit wxGrid.
Ich möchte einige Zellen nur für die Eingabe von Zahlen und Komma oder Punkt formatieren.
Zu dem Thema hab ich schon etwas ähnliches gefunden
http://www.c-plusplus.net/forum/viewtopic-var-t-is-126891-and-highlight-is-zahleneingabe.html
http://forums.wxwidgets.org/viewtopic.php?t=15978&highlight=wxnumberctrlwie setzt das in wxGrid und einigen Zellen um?
Schreibt man eine Eigene Klasse wie der Link aus dem wxWidgets Discussion Forum es beschreibt oder kann man einfach nur m_m_eingabeGridCtrl->SetValidator(... benutzen.Gruß Califax :xmas1:
-
Hallo
Hab wie ich hoffe eine Lösung gefunden.
Hier der Code
GridDoubleZahlenEditor.h#pragma once #include <wx/grid.h> class GridDoubleZahlenEditor :public wxGridCellFloatEditor { public: GridDoubleZahlenEditor(int width = -1, int precision = -1); ~GridDoubleZahlenEditor(void); void Create(wxWindow* parent, wxWindowID id, wxEvtHandler* evtHandler); void StartingKey(wxKeyEvent& event); bool IsAcceptedKey(wxKeyEvent& event); };
GridDoubleZahlenEditor.cpp
#include "GridDoubleZahlenEditor.h" GridDoubleZahlenEditor::GridDoubleZahlenEditor(int width, int precision) { } GridDoubleZahlenEditor::~GridDoubleZahlenEditor(void) { } void GridDoubleZahlenEditor::Create(wxWindow* parent, wxWindowID id, wxEvtHandler* evtHandler) { wxTextValidator textValidator(wxFILTER_NUMERIC); wxGridCellTextEditor::Create(parent,id, evtHandler); this->Text()->SetValidator( textValidator); } void GridDoubleZahlenEditor::StartingKey(wxKeyEvent& event) { } bool GridDoubleZahlenEditor::IsAcceptedKey(wxKeyEvent& event) { if ( wxGridCellEditor::IsAcceptedKey(event) ) { int keycode = event.GetKeyCode(); if ( (keycode < 128) && wxIsxdigit(keycode) ) { return true; } } return false; }
Aufgerufen in der Klasse MeinPanel
{ GridDoubleZahlenEditor* editor = new GridDoubleZahlenEditor(-1,2); //editor->SetParameters(wxT("100")); m_grid1->SetCellEditor(3, 0, editor); }
Dabei bin ich auf die nächsten Probleme gestoßen.
Eine Fehlermeldung, mit der ich nichts richtiges anfangen kann.
-----------------------------------
R6025
-pure virtual function call
------------------------------------
Was kann ich machen das die Klasse GridDoubleZahlenEditor sauber läuft?Dann gibt es noch ein paar Sachen wo ich nicht weiter komme.
1.Wie kann ich anstelle des Punktes ein Komma schreiben?
(Oder beißt sich das mit wxGridCellFloatEditor, sollte man da vielleicht wxGridCellTextEditor verwenden.)2.Wie kann man Doppel Kommas vermeiden?
3.Wie kann ich nur 2 Stellen nach dem Komma einstellen ?
(mit “GridDoubleZahlenEditor* editor = new GridDoubleZahlenEditor(-1,2);” funktioniert das nicht)Gruß Califax
Einen Guten rutsch
-
Hallo
ein gesundes neues Jahr
zum Fehler
-----------------------------------
R6025
-pure virtual function call
------------------------------------
kann ich melden .
Es lag wahrscheinlich an einer beschädigten wx Bibliothek.
Ich hab alle neu erstellt und der Fehler war weg.Nun muss ich noch die restlichen punkte ab arbeiten.
Gruß Califax
-
Hallo
ich versuche noch mal von vorn anzufangen.
Mein Ziel ist es in einer wxGrid eine Zelle anzuklicken und die Zelle so zu Formatieren das der Bediener nur die Möglichkeit hat Ziffern und Komma einzugeben.
Es gibt die Möglichkeit von validators und wxGridCellTextEditor.
Ich hab mich für wxGridCellTextEditor entschieden da ich noch ein paar Besonderheiten mit einbauen will.
Der Code sieht wie folgt aus .
GridDoubleZahlenEditor.h
#pragma once #include <wx/grid.h> class GridDoubleZahlenEditor :public wxGridCellTextEditor { public: GridDoubleZahlenEditor(); ~GridDoubleZahlenEditor(void); virtual void Create(wxWindow* parent, wxWindowID id, wxEvtHandler* evtHandler); virtual void StartingKey(wxKeyEvent& event); virtual bool IsAcceptedKey(wxKeyEvent& event); virtual void BeginEdit(int row, int col, wxGrid* grid); virtual bool EndEdit(int row, int col, wxGrid *grid) ; private: wxString alterWert; wxString m_startValue; };
GridDoubleZahlenEditor.cpp
#include "GridDoubleZahlenEditor.h" GridDoubleZahlenEditor::GridDoubleZahlenEditor() :alterWert(_T("")) { } GridDoubleZahlenEditor::~GridDoubleZahlenEditor(void) { } void GridDoubleZahlenEditor::Create(wxWindow* parent, wxWindowID id, wxEvtHandler* evtHandler) { wxTextValidator textValidator(wxFILTER_NUMERIC); wxGridCellTextEditor::Create(parent,id, evtHandler); this->Text()->SetValidator( textValidator); } void GridDoubleZahlenEditor::StartingKey(wxKeyEvent& event) { int keycode = (int)event.GetKeyCode(); if ((keycode < 128) ) { wxGridCellTextEditor::StartingKey(event); return; } event.Skip(); } bool GridDoubleZahlenEditor::IsAcceptedKey(wxKeyEvent& event) { if ( wxGridCellTextEditor::IsAcceptedKey(event) ) { int Tastenkode = event.GetKeyCode(); if ( (Tastenkode < 128) ) { return true; } } return false; } void GridDoubleZahlenEditor::BeginEdit(int row, int col, wxGrid* grid) { wxASSERT_MSG(m_control,wxT("Der wxGridCellTextEditor muss zuerst erstellt werden!")); Text()->SetValue(_T("0,00")); Text()->SetFocus(); } bool GridDoubleZahlenEditor::EndEdit(int row, int col, wxGrid *grid) { wxString text(Text()->GetValue()); grid->GetTable()->SetValue(row, col, text); return true; }
Wenn ich nun eine Zelle auswähle (OnGridSelectCell(wxGridEvent& event1)) und dann eine Taste(Ziffer) drücke(OnKeyDown)
void grid_keyPanel::OnGridEditorShown(wxGridEvent& event1) { GridDoubleZahlenEditor* editor = new GridDoubleZahlenEditor(); m_grid1->SetCellEditor(row,col, editor); }
, wird aufgerufen und damit wie zu sehen auch m_grid1->SetCellEditor(row,col, editor); .
Damit startet BeginEdit und in der Zelle wird 0,00 angezeigt und der Körser blinkt vor dem Komma und beim zweiten drücken einer Taste (Ziffer) wird erst der Keycode geschrieben, es sollte aber schon bei ersten OnKeyDown der Keycode geschrieben werden.
Was mache ich falsch?Und warum kann ich nur unter bestimmten Bedingungen die Funktion
bool GridDoubleZahlenEditor::IsAcceptedKey(wxKeyEvent& event)
aufrufen.
Wenn eine Zelle ausgewählt( OnGridSelectCell)wird und die Zelle einen Wert enthält und dann OnKeyDown ausgelöst, wird erst die Funktion (IsAcceptedKey(wxKeyEvent& event)) aufgerufen.
Warum erst dann und nicht sofort (also bei leerer Zelle)?
Kann mir jemand helfen?
Gruß Califax
-
Hallo
Hab mal an meiner Sache weiter gearbeitet und folgenden Code geschrieben.
Es funktioniert fast alles wie gewollt.Es kann eine Spalte nur mit Zahlen eingegeben werden Doppelpunkt ist nicht möglich
und die Nachkommastellen sind auf 2 eingestellt.MeinGridCellEditor* editor = new MeinGridCellEditor(-1,1,wxFILTER_NUMERIC); m_grid1->RegisterDataType(wxGRID_VALUE_STRING,new wxGridCellFloatRenderer(-1,2), editor);
Ich würde mich freuen, wenn mal einer seine vernichtende Meinung zum Code abgibt.
MeinGridCellEditor.h
#pragma once #include <wx/grid.h> #include <wx/string.h> #include "STL_TextValidator.h" class MeinGridCellEditor :public wxGridCellTextEditor { public: MeinGridCellEditor(int row = -1,int col = -1,long style = wxFILTER_NONE); ~MeinGridCellEditor(void); virtual void Create(wxWindow* parent , wxWindowID id , wxEvtHandler* evtHandler); virtual bool IsAcceptedKey(wxKeyEvent& event); virtual void StartingKey(wxKeyEvent& event); virtual void BeginEdit(int row, int col, wxGrid* grid); virtual bool EndEdit(int row, int col, wxGrid *grid) ; private: wxString m_AlterWert; wxGrid* m_grid; int m_col; int m_row; int m_tmp_row; int m_tmp_col; long m_style; bool m_signalton; STL_TextValidator textValidator; };
MeinGridCellEditor.cpp
#include "MeinGridCellEditor.h" MeinGridCellEditor::MeinGridCellEditor(int row,int col,long style) : m_grid(NULL) , m_col(0) , m_row(0) , m_tmp_row(-1) , m_tmp_col(-1) { m_row = row; m_col = col; m_style= style; } MeinGridCellEditor::~MeinGridCellEditor(void) { } bool MeinGridCellEditor::IsAcceptedKey(wxKeyEvent& event) { if ( wxGridCellEditor::IsAcceptedKey(event) ) { int Tastenkode = event.GetKeyCode(); // Hier werden alle Tasteneingaben bis ASCII 128 erlaubt if (Tastenkode < 128) { return true; } } return false; } void MeinGridCellEditor::Create(wxWindow* parent , wxWindowID id , wxEvtHandler* evtHandler) { wxGridCellTextEditor::Create(parent,id, evtHandler); } void MeinGridCellEditor::BeginEdit(int row, int col, wxGrid* grid) { wxASSERT_MSG(m_control,wxT("Der wxGridCellTextEditor muss zuerst erstellt werden!")); m_tmp_row = row; m_tmp_col = col; if (grid->GetRows() - 1 == row) { // Hier wird wenn erwünscht eine Zeile in die Tabelle eingefügt // grid->AppendRows(1, false); } // Hier wird wenn wahr eine Spalte für Zahleneingabe ausgewählt if (m_col == m_tmp_col) { textValidator.SetStyle(wxFILTER_NUMERIC); this->Text()->SetValidator(textValidator); } else { textValidator.SetStyle(wxFILTER_NONE); this->Text()->SetValidator(textValidator); } wxGridCellTextEditor::BeginEdit(row, col, grid); } void MeinGridCellEditor::StartingKey(wxKeyEvent& event) { /// Ist noch nicht IO nochmal prüfen int keyCode = event.GetKeyCode(); if (m_col == m_tmp_col) { if ((keyCode < 128) && ( wxIsdigit(keyCode) || keyCode == ',' || keyCode == '.')) { wxGridCellTextEditor::StartingKey(event); return; } } else { if ((keyCode < 128)) { wxGridCellTextEditor::StartingKey(event); return; } } event.Skip(); } bool MeinGridCellEditor::EndEdit(int row, int col, wxGrid *grid) { /// Ist noch nicht IO nochmal prüfen wxString text(Text()->GetValue()); grid->GetTable()->SetValue(row, col, text); return true; }
STL_TextValidator.h
#pragma once #include <wx/valtext.h> class STL_TextValidator :public wxTextValidator { DECLARE_DYNAMIC_CLASS(STL_TextValidator) public: STL_TextValidator(const wxTextValidator& val); STL_TextValidator(long style = wxFILTER_NONE, wxString *val = 0); virtual wxObject* Clone(void)const; virtual void OnChar(wxKeyEvent& event); ~STL_TextValidator(void); DECLARE_EVENT_TABLE() };
STL_TextValidator.cpp
#include "STL_TextValidator.h" IMPLEMENT_DYNAMIC_CLASS(STL_TextValidator, wxValidator) BEGIN_EVENT_TABLE(STL_TextValidator, wxTextValidator) EVT_CHAR(STL_TextValidator::OnChar) END_EVENT_TABLE() STL_TextValidator::STL_TextValidator(const wxTextValidator& val) { } STL_TextValidator::STL_TextValidator(long style , wxString *val) { } STL_TextValidator::~STL_TextValidator(void) { } void STL_TextValidator::OnChar(wxKeyEvent& event) { if ( m_validatorWindow ) { int keyCode = event.GetKeyCode(); wxString m_AlterWert(((wxTextCtrl*)m_validatorWindow)->GetValue()); // Nur Zahlen Eingabe zulassen if(wxTextValidator::GetStyle() ==wxFILTER_NUMERIC) { if (wxIsdigit(keyCode) || keyCode == '.' || keyCode == ',' ||keyCode<WXK_SPACE|| keyCode== WXK_DELETE|| keyCode=='-' || keyCode=='+' || keyCode > WXK_START) { switch (keyCode) { case WXK_NUMPAD_DECIMAL: case '.': if ((!(m_AlterWert.Find(wxT('.'))==-1))) //keine doppelten Punkte zulassen { return; } break; case ',': case '-': case '+': return; break; default: wxBell(); event.Skip(false); break; } } else { wxBell(); event.Skip(); } } } event.Skip(); } wxObject* STL_TextValidator::Clone(void)const { return new STL_TextValidator(*this); }
Gruß Califax
-
Hallo
Wenn es interessiert hier ist der Code der zu 90 Prozent wie oben beschrieben funktioniert.
// Speicher reservieren wxLocale *sprache = new wxLocale(wxLANGUAGE_GERMAN, wxLOCALE_CONV_ENCODING); MeinGridCellEditor* editor = new MeinGridCellEditor(-1,1,wxFILTER_NUMERIC); m_grid1->RegisterDataType(wxGRID_VALUE_STRING,new wxGridCellFloatRenderer(-1,2), editor);
Dann noch eine Sache am Rande.
Wenn ihr einen double Wert in String konvertirt schaut mal auf den Punkt im String.double d_wert = 0.77; wxString s_str= s_str.Format(wxT("%.2f"),d_wert);
Komentiert dann mal die Zeile
wxLocale *sprache = new wxLocale(wxLANGUAGE_GERMAN, wxLOCALE_CONV_ENCODING);
aus und schaut wieder auf den Punkt im String.
Nun weiter im Code.
MeinGridCellEditor.h#pragma once #include <wx/grid.h> #include <wx/string.h> #include "STL_TextValidator.h" class MeinGridCellEditor :public wxGridCellTextEditor { public: MeinGridCellEditor(int row = -1,int col = -1,long style = wxFILTER_NONE); ~MeinGridCellEditor(void); private: wxString m_AlterWert; wxGrid* m_grid; int m_col; int m_row; int m_tmp_row; int m_tmp_col; long m_style; bool m_signalton; STL_TextValidator textValidator; virtual void Create(wxWindow* parent , wxWindowID id , wxEvtHandler* evtHandler); virtual bool IsAcceptedKey(wxKeyEvent& event); virtual void StartingKey(wxKeyEvent& event); virtual void BeginEdit(int row, int col, wxGrid* grid); virtual bool EndEdit(int row, int col, wxGrid *grid) ; };
MeinGridCellEditor.cpp
#include "MeinGridCellEditor.h" MeinGridCellEditor::MeinGridCellEditor(int row,int col,long style) : m_grid(NULL) , m_col(0) , m_row(0) , m_tmp_row(-1) , m_tmp_col(-1) { m_row = row; m_col = col; m_style= style; } MeinGridCellEditor::~MeinGridCellEditor(void) { } bool MeinGridCellEditor::IsAcceptedKey(wxKeyEvent& event) { if ( wxGridCellEditor::IsAcceptedKey(event) ) { int Tastenkode = event.GetKeyCode(); // Hier werden alle Tasteneingaben bis ASCII 128 erlaubt if (Tastenkode < 128) { return true; } } return false; } void MeinGridCellEditor::Create(wxWindow* parent , wxWindowID id , wxEvtHandler* evtHandler) { wxGridCellTextEditor::Create(parent,id, evtHandler); } void MeinGridCellEditor::BeginEdit(int row, int col, wxGrid* grid) { wxASSERT_MSG(m_control,wxT("Der wxGridCellTextEditor muss zuerst erstellt werden!")); m_tmp_row = row; m_tmp_col = col; if (grid->GetRows() - 1 == row) { // Hier wird wenn erwünscht eine Zeile in die Tabelle eingefügt // grid->AppendRows(1, false); } // Hier wird wenn wahr eine Spalte für Zahleneingabe ausgewählt if (m_col == m_tmp_col) { textValidator.SetStyle(wxFILTER_NUMERIC); this->Text()->SetValidator(textValidator); } else { textValidator.SetStyle(wxFILTER_NONE); this->Text()->SetValidator(textValidator); } wxGridCellTextEditor::BeginEdit(row, col, grid); } void MeinGridCellEditor::StartingKey(wxKeyEvent& event) { int keyCode = event.GetKeyCode(); if (m_col == m_tmp_col) { if ((keyCode < 128) && ( wxIsdigit(keyCode) || keyCode == ',' || keyCode == '.')) { wxGridCellTextEditor::StartingKey(event); return; } } else { if ((keyCode < 128)) { wxGridCellTextEditor::StartingKey(event); return; } } event.Skip(); } bool MeinGridCellEditor::EndEdit(int row, int col, wxGrid *grid) { wxString text(Text()->GetValue()); // Hier wir geschaut ob das Komma an der Ersten stelle steht if(text.First(',')== 0) { // wenn wahr wird eine Null vor den Komma geschrieben wxString str; str= text.BeforeFirst(','); str <<wxT("0"); str <<text; text.Clear(); text <<str; } grid->GetTable()->SetValue(row, col, text); return true; }
STL_TextValidator.h
#pragma once #include <wx/valtext.h> class STL_TextValidator :public wxTextValidator { DECLARE_DYNAMIC_CLASS(STL_TextValidator) public: STL_TextValidator(const wxTextValidator& val); STL_TextValidator(long style = wxFILTER_NONE, wxString *val = 0); ~STL_TextValidator(void); private: virtual wxObject* Clone(void)const; virtual void OnChar(wxKeyEvent& event); DECLARE_EVENT_TABLE() };
STL_TextValidator.cpp
#include "STL_TextValidator.h" IMPLEMENT_DYNAMIC_CLASS(STL_TextValidator, wxValidator) BEGIN_EVENT_TABLE(STL_TextValidator, wxTextValidator) EVT_CHAR(STL_TextValidator::OnChar) END_EVENT_TABLE() STL_TextValidator::STL_TextValidator(const wxTextValidator& val) { } STL_TextValidator::STL_TextValidator(long style , wxString *val) { } STL_TextValidator::~STL_TextValidator(void) { } void STL_TextValidator::OnChar(wxKeyEvent& event) { if ( m_validatorWindow ) { int keyCode = event.GetKeyCode(); wxString m_AlterWert(((wxTextCtrl*)m_validatorWindow)->GetValue()); // Nur Zahlen Eingabe zulassen if(wxTextValidator::GetStyle() ==wxFILTER_NUMERIC) { if (wxIsdigit(keyCode) || keyCode == '.' || keyCode == ',' ||keyCode<WXK_SPACE|| keyCode== WXK_DELETE|| keyCode=='-' || keyCode=='+' || keyCode > WXK_START) { switch (keyCode) { case WXK_NUMPAD_DECIMAL: case '.': if(keyCode == '.') { return; } case ',': if (m_AlterWert.Find(',')==-1) //keine doppelten Komma zulassen { ((wxTextCtrl*)m_validatorWindow)->WriteText(_T(",")); return; } else { return; } break; case '-': case '+': return; break; default: event.Skip(); break; } } else { wxBell(); event.Skip(); } } } event.Skip(); } wxObject* STL_TextValidator::Clone(void)const { return new STL_TextValidator(*this); }
Das sind bestimmt noch ein paar Fehler drin, aber im großen ganzen erfüllt es meinen Zweck.
Der Bediener kann in einer Spalte nur Zahlen eingeben es wird Komma geschrieben und die zwei Stellen nach dem Komma.Viel spaß
Califax