gpt4 book ai didi

c++ - wxTextValidator 导致崩溃

转载 作者:行者123 更新时间:2023-11-28 01:33:10 24 4
gpt4 key购买 nike

我有一个对话窗口,其中包含一些动态控件。基本上,在构建时我将一个指向结构的指针传递给它,在这个结构中是一个容器 std::pair<wxString,wxString> .对于其中的每一个,我需要创建另一行三个控件,一个 wxTextCtrl , wxChoice和一个 wxButton .

这部分有效,基于容器中的可用项目,我在对话框构建时成功创建了这些项目。我也用 wxTextValidator连接 wxTextCtrl第一个wxString在这对。所以如果容器中有三对,我会有三个 wxTextCtrl s 被创建,并且每个都有一个验证器到它各自的 wxString .

根据wxID_OK在对话框中,文本验证器工作并且我作为指针传递给它的原始结构包含正确的数据。

但是,我还在我的对话框中添加了一个按钮,它应该允许创建新的 std::pair<wxString,wxString>记录在容器中。如果我这样做,在 wxID_OK ,应用程序崩溃。 DrMingW 使指向 wxString 的指针看起来像无效,但这是不可能的,因为单击按钮时我正在我的容器中创建一条新记录,并指向 wxTextValidator到这个新创建的记录。它存储在对话框之外,因此不会在关闭对话框时失效。

我的数据结构:

struct StoryNodeData
{
wxString title;
wxString text;
std::vector<std::pair<wxString,wxString>> options;
};

我的对话框标题:

#ifndef STORYDIALOG_H
#define STORYDIALOG_H

#include "flowchart.hpp"

#include <map>

//(*Headers(StoryDialog)
#include <wx/bmpbuttn.h>
#include <wx/button.h>
#include <wx/choice.h>
#include <wx/dialog.h>
#include <wx/gbsizer.h>
#include <wx/scrolwin.h>
#include <wx/sizer.h>
#include <wx/textctrl.h>
//*)

class StoryDialog: public wxDialog
{
public:

StoryDialog(wxWindow* parent,StoryNodeData* data, wxArrayString titles,wxWindowID id=wxID_ANY,const wxPoint& pos=wxDefaultPosition,const wxSize& size=wxDefaultSize);
virtual ~StoryDialog();

void HandleOptionDelete(wxCommandEvent& e);

//(*Declarations(StoryDialog)
wxButton* OptionButton;
wxFlexGridSizer* OptionsSizer;
wxScrolledWindow* OptionsWindow;
wxTextCtrl* EventTextCtrl;
wxTextCtrl* TitleTextCtrl;
//*)

protected:

//(*Identifiers(StoryDialog)
static const long ID_TEXTCTRL1;
static const long ID_TEXTCTRL2;
static const long ID_BUTTON1;
static const long ID_TEXTCTRL3;
static const long ID_CHOICE1;
static const long ID_BITMAPBUTTON1;
static const long ID_SCROLLEDWINDOW1;
//*)

private:

//(*Handlers(StoryDialog)
void OnNewOptionButtonClick(wxCommandEvent& event);
void OnBitmapButton1Click(wxCommandEvent& event);
//*)

std::map<wxObject*,std::tuple<wxTextCtrl*, wxChoice*, std::size_t>> m_optionCtrls;
StoryNodeData* m_data;
wxArrayString m_titles;

void ConstructOption(wxString* text, wxString* title);

DECLARE_EVENT_TABLE()
};

#endif

以及对话框实现:

#include "StoryDialog.h"

#include <wx/artprov.h>
#include <wx/valgen.h>

//(*InternalHeaders(StoryDialog)

#include <wx/artprov.h>

#include <wx/bitmap.h>

#include <wx/image.h>

#include <wx/intl.h>

#include <wx/string.h>

//*)

//(*IdInit(StoryDialog)

const long StoryDialog::ID_TEXTCTRL1 = wxNewId();

const long StoryDialog::ID_TEXTCTRL2 = wxNewId();

const long StoryDialog::ID_BUTTON1 = wxNewId();

const long StoryDialog::ID_TEXTCTRL3 = wxNewId();

const long StoryDialog::ID_CHOICE1 = wxNewId();

const long StoryDialog::ID_BITMAPBUTTON1 = wxNewId();

const long StoryDialog::ID_SCROLLEDWINDOW1 = wxNewId();

//*)

BEGIN_EVENT_TABLE(StoryDialog,wxDialog)
//(*EventTable(StoryDialog)
//*)
END_EVENT_TABLE()

StoryDialog::StoryDialog(wxWindow* parent,StoryNodeData* data, wxArrayString titles,wxWindowID id,const wxPoint& pos,const wxSize& size)
{
//(*Initialize(StoryDialog)

wxBitmapButton* BitmapButton1;

wxChoice* Choice1;

wxFlexGridSizer* FlexGridSizer1;

wxGridBagSizer* GridBagSizer1;

wxStaticBoxSizer* StaticBoxSizer1;

wxStdDialogButtonSizer* StdDialogButtonSizer1;

wxTextCtrl* TextCtrl1;


Create(parent, wxID_ANY, _("New Event"), wxDefaultPosition, wxDefaultSize, wxSTAY_ON_TOP|wxCAPTION|wxRESIZE_BORDER|wxCLOSE_BOX|wxMAXIMIZE_BOX|wxMINIMIZE_BOX|wxSIMPLE_BORDER, _T("wxID_ANY"));

GridBagSizer1 = new wxGridBagSizer(0, 0);

GridBagSizer1->AddGrowableCol(0);

GridBagSizer1->AddGrowableRow(1);

TitleTextCtrl = new wxTextCtrl(this, ID_TEXTCTRL1, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, wxTextValidator(wxFILTER_NONE,&data->title), _T("ID_TEXTCTRL1"));

GridBagSizer1->Add(TitleTextCtrl, wxGBPosition(0, 0), wxDefaultSpan, wxALL|wxEXPAND, 5);

EventTextCtrl = new wxTextCtrl(this, ID_TEXTCTRL2, wxEmptyString, wxDefaultPosition, wxSize(259,138), wxTE_MULTILINE|wxVSCROLL, wxTextValidator(wxFILTER_NONE,&data->text), _T("ID_TEXTCTRL2"));

GridBagSizer1->Add(EventTextCtrl, wxGBPosition(1, 0), wxDefaultSpan, wxALL|wxEXPAND, 5);

StdDialogButtonSizer1 = new wxStdDialogButtonSizer();

StdDialogButtonSizer1->AddButton(new wxButton(this, wxID_OK, wxEmptyString));

StdDialogButtonSizer1->AddButton(new wxButton(this, wxID_CANCEL, wxEmptyString));

StdDialogButtonSizer1->Realize();

GridBagSizer1->Add(StdDialogButtonSizer1, wxGBPosition(2, 0), wxGBSpan(1, 2), wxALL|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL, 5);

StaticBoxSizer1 = new wxStaticBoxSizer(wxHORIZONTAL, this, _("Options"));

FlexGridSizer1 = new wxFlexGridSizer(2, 1, 0, 0);

FlexGridSizer1->AddGrowableCol(0);

FlexGridSizer1->AddGrowableRow(1);

OptionButton = new wxButton(this, ID_BUTTON1, _("New Option"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_BUTTON1"));

FlexGridSizer1->Add(OptionButton, 1, wxALL|wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL, 5);

OptionsWindow = new wxScrolledWindow(this, ID_SCROLLEDWINDOW1, wxDefaultPosition, wxDefaultSize, wxSIMPLE_BORDER|wxVSCROLL, _T("ID_SCROLLEDWINDOW1"));

OptionsSizer = new wxFlexGridSizer(0, 3, 0, 0);

OptionsSizer->AddGrowableCol(0);

TextCtrl1 = new wxTextCtrl(OptionsWindow, ID_TEXTCTRL3, _("Text"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_TEXTCTRL3"));

OptionsSizer->Add(TextCtrl1, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);

Choice1 = new wxChoice(OptionsWindow, ID_CHOICE1, wxDefaultPosition, wxDefaultSize, 0, 0, 0, wxDefaultValidator, _T("ID_CHOICE1"));

OptionsSizer->Add(Choice1, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);

BitmapButton1 = new wxBitmapButton(OptionsWindow, ID_BITMAPBUTTON1, wxArtProvider::GetBitmap(wxART_MAKE_ART_ID_FROM_STR(_T("wxART_DELETE")),wxART_BUTTON), wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW, wxDefaultValidator, _T("ID_BITMAPBUTTON1"));

OptionsSizer->Add(BitmapButton1, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);

OptionsWindow->SetSizer(OptionsSizer);

OptionsSizer->Fit(OptionsWindow);

OptionsSizer->SetSizeHints(OptionsWindow);

FlexGridSizer1->Add(OptionsWindow, 1, wxALL|wxEXPAND, 5);

StaticBoxSizer1->Add(FlexGridSizer1, 1, wxEXPAND, 5);

GridBagSizer1->Add(StaticBoxSizer1, wxGBPosition(0, 1), wxGBSpan(2, 1), wxALL|wxEXPAND, 5);

SetSizer(GridBagSizer1);

GridBagSizer1->Fit(this);

GridBagSizer1->SetSizeHints(this);


Connect(ID_BUTTON1,wxEVT_COMMAND_BUTTON_CLICKED,(wxObjectEventFunction)&StoryDialog::OnNewOptionButtonClick);

//*)


OptionsWindow->SetScrollRate(5,5);

OptionsWindow->DestroyChildren();

Bind(wxEVT_BUTTON, &StoryDialog::HandleOptionDelete, this);

m_data = data;
m_titles = titles;

// construct the existing options
for(auto itr = m_data->options.begin(); itr != m_data->options.end(); ++itr)
{
auto title = &((*itr).first);
auto text = &((*itr).second);

ConstructOption(text,title);
}
}

StoryDialog::~StoryDialog()
{
//(*Destroy(StoryDialog)
//*)
}


void StoryDialog::HandleOptionDelete(wxCommandEvent& e)
{
auto b = e.GetEventObject();
auto itr = m_optionCtrls.find(b);
if(m_optionCtrls.end() != itr)
{
auto button = itr->first;
auto pa = itr->second;
m_optionCtrls.erase(itr);

OptionsSizer->Detach(std::get<0>(pa));
OptionsSizer->Detach(std::get<1>(pa));
OptionsSizer->Detach(reinterpret_cast<wxBitmapButton*>(button));

std::get<0>(pa)->Destroy();
std::get<1>(pa)->Destroy();
reinterpret_cast<wxBitmapButton*>(button)->Destroy();

auto index = std::get<2>(pa);
auto itr = m_data->options.begin() + index;
m_data->options.erase(itr);
}

OptionsSizer->Layout();
OptionsWindow->SetSizer(OptionsSizer);
SendSizeEvent();

e.Skip(true);
}

void StoryDialog::OnNewOptionButtonClick(wxCommandEvent& event)
{
m_data->options.push_back(std::make_pair("",""));

auto itr = m_data->options.end()-1;

auto text = &((*(itr)).second);
auto title = &((*(itr)).first);

ConstructOption(text,title);
}

void StoryDialog::ConstructOption(wxString* text, wxString* title)
{
long tId = wxNewId();
long cId = wxNewId();
long bId = wxNewId();

auto optionTextCtrl = new wxTextCtrl(OptionsWindow, tId, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, wxTextValidator(wxFILTER_NONE,text));

OptionsSizer->Add(optionTextCtrl, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);

auto optionTitleCtrl = new wxChoice(OptionsWindow, cId, wxDefaultPosition, wxDefaultSize, m_titles, 0, wxGenericValidator(title));

OptionsSizer->Add(optionTitleCtrl, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);

auto deleteButtonCtrl = new wxBitmapButton(OptionsWindow, bId, wxArtProvider::GetBitmap(wxART_MAKE_ART_ID_FROM_STR(_T("wxART_DELETE")),wxART_BUTTON), wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW, wxDefaultValidator);

OptionsSizer->Add(deleteButtonCtrl, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);

OptionsSizer->Layout();
OptionsWindow->SetSizer(OptionsSizer);
SendSizeEvent();

m_optionCtrls[deleteButtonCtrl] = std::make_tuple(optionTextCtrl,optionTitleCtrl,m_optionCtrls.size()-1);
}

您会注意到,无论是基于提供的数据还是用户通过控件添加新数据,我创建动态控件的方式都是相同的。唯一的区别是在添加新记录时,我首先在容器中创建记录

最佳答案

指向 std::vector<> 元素的指针可以(并且将)在 vector 内容更改时失效,例如当你向它附加更多元素时,你不能这样做。

相反,您需要使用不会移动其值的容器(例如 std::[unordered_]map<> )或存储 unique_ptr<> s 在你的 vector 中。

关于c++ - wxTextValidator 导致崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50697451/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com