【问题标题】:wxpython Segmentation Fault when deleting item from ListCtrl从 ListCtrl 删除项目时出现 wxpython 分段错误
【发布时间】:2018-10-01 04:13:34
【问题描述】:

只要程序到达self.DeleteItem,它就会崩溃并打印Segmentation Fault (Core Dumped)。删除self.DeleteItem 后,它不再崩溃,但我们失去了删除一行的能力。我不确定这有什么问题,因为它只有一条线坏了。你能帮我看看有什么问题吗?

代码

import wx
from wx.lib.mixins.listctrl import ListCtrlAutoWidthMixin
from scrapy.crawler import CrawlerProcess

from spider.spider import WIPOSpider
from settings import settings
from processor import process_xls

class MainFrame(wx.Frame):

    TITLE = 'Neko'
    FRAME_MIN_SIZE = (820, 220)
    DEFAULT_BORDER_SIZE = 10

    ADD_LABEL = 'Add'
    REMOVE_LABEL = 'Remove'
    START_LABEL = 'Start'

    FILE_LABEL = 'File'
    SIZE_LABEL = 'Size'
    PERCENT_LABEL = 'Percent'
    ETA_LABEL = 'ETA'
    SPEED_LABEL = 'Speed'
    STATUS_LABEL = 'Status'
    STATUS_LIST = {
        'filename': (0, FILE_LABEL, 300, False),
        'size': (1, SIZE_LABEL, 80, False),
        'percent': (2, PERCENT_LABEL, 80, False),
        'eta': (3, ETA_LABEL, 80, False),
        'speed': (4, SPEED_LABEL, 80, False),
        'status': (5, STATUS_LABEL, 80, False),
    }

    def __init__(self, *args, **kwargs):
        super(MainFrame, self).__init__(*args, **kwargs)

        self.index = 0

        self.SetTitle(self.TITLE)
        self.SetSize(self.FRAME_MIN_SIZE)

        self._panel = wx.Panel(self)
        self._vertical_box = wx.BoxSizer(wx.VERTICAL)

        # Status List
        self._status_list = ListCtrl(self.STATUS_LIST,
                                parent=self._panel,
                                style=wx.LC_REPORT | wx.LEFT | wx.RIGHT)
        self._horizontal_box_status_list = wx.BoxSizer(wx.HORIZONTAL)
        self._horizontal_box_status_list.Add(self._status_list,
                                        proportion=1, flag=wx.EXPAND)

        status_list_buttons_data = {
            ('Add', self.ADD_LABEL, (-1, -1), self._on_add, wx.Button),
            ('remove', self.REMOVE_LABEL, (-1, -1), self._on_remove, wx.Button),
            ('start', self.START_LABEL, (-1, -1), self._on_start, wx.Button),
        }

        # Create buttons vertically
        self._vertical_control_box = wx.BoxSizer(wx.VERTICAL)
        for item in status_list_buttons_data:
            name, label, size, evt_handler, parent = item

            button = parent(self._panel, size=size)

            if parent == wx.Button:
                button.SetLabel(label)

            if evt_handler is not None:
                button.Bind(wx.EVT_BUTTON, evt_handler)

            self._vertical_control_box.Add(button,
                                        flag=wx.LEFT|wx.BOTTOM|wx.EXPAND,
                                        proportion=1,
                                        border=self.DEFAULT_BORDER_SIZE)

        self._horizontal_box_status_list.Add(self._vertical_control_box)
        self._vertical_box.Add(self._horizontal_box_status_list,
                            flag=wx.EXPAND|wx.LEFT|wx.RIGHT|wx.TOP,
                            border=self.DEFAULT_BORDER_SIZE)

        # Set Sizer
        self._panel.SetSizerAndFit(self._vertical_box)

    def _on_add(self, event):
        file_dialog = wx.FileDialog(self)
        file_dialog.Show()

        if file_dialog.ShowModal() == wx.ID_OK:
            file_path = file_dialog.GetPath()
            self._status_list.InsertItem(self.index, file_path)

            self.index += 1

    def _on_remove(self, event):
        selected = self._status_list.get_selected()

        if selected:
            self._status_list.remove_row(selected)

    def _on_start(self, event):
        for item_count in range(0, self._status_list.GetItemCount()):
            item = self._status_list.GetItem(item_count, col=0)
            data = process_xls(item.GetText())

            # Start spider
            if data:
                process = CrawlerProcess(settings['BOT_SETTINGS'])
                process.crawl(WIPOSpider(data))
                process.start()

# Copied from
# https://github.com/MrS0m30n3/youtube-dl-gui/blob/57eb51ccc8e2df4e8c766b31d677513adb5c86cb/youtube_dl_gui/mainframe.py#L1095
class ListCtrl(wx.ListCtrl, ListCtrlAutoWidthMixin):

    """Custom ListCtrl widget.
    Args:
        columns (dict): See MainFrame class STATUSLIST_COLUMNS attribute.
    """

    def __init__(self, columns, *args, **kwargs):
        super(ListCtrl, self).__init__(*args, **kwargs)
        ListCtrlAutoWidthMixin.__init__(self)
        self.columns = columns
        self._list_index = 0
        self._set_columns()

    def remove_row(self, row_number):
        self.DeleteItem(row_number)
        self._list_index -= 1

    def get_selected(self):
        return self.GetNextItem(-1, wx.LIST_NEXT_ALL, wx.LIST_STATE_SELECTED)

    def _set_columns(self):
        """Initializes ListCtrl columns.
        See MainFrame STATUSLIST_COLUMNS attribute for more info. """
        for column_item in sorted(self.columns.values()):
            self.InsertColumn(column_item[0], column_item[1], width=wx.LIST_AUTOSIZE_USEHEADER)

            # If the column width obtained from wxLIST_AUTOSIZE_USEHEADER
            # is smaller than the minimum allowed column width
            # then set the column width to the minumum allowed size
            if self.GetColumnWidth(column_item[0]) < column_item[2]:
                self.SetColumnWidth(column_item[0], column_item[2])

            # Set auto-resize if enabled
            if column_item[3]:
                self.setResizeColumn(column_item[0])

【问题讨论】:

    标签: python c++ wxpython wxwidgets


    【解决方案1】:

    显然,ListCtrlListCtrlAutoWidthMixin 的子分类存在问题。
    如果你放弃你的子类并使用标准的ListCtrl,代码就可以工作。

    self._status_list = wx.ListCtrl(self, -1,
                            style=wx.LC_REPORT)
    for column_item in self.STATUS_LIST.values():
        self._status_list.InsertColumn(column_item[0], column_item[1], width=column_item[2])
    

    那么函数_on_remove就变成了:

    def _on_remove(self, event):
        selected = self._status_list.GetNextItem(-1, wx.LIST_NEXT_ALL, wx.LIST_STATE_SELECTED)
        if selected >= 0:
            self._status_list.DeleteItem(selected)
    

    注意:您当前将status_list_buttons_data 定义为set,如果这是list,您的按钮将显示得更加一致。我相信集合是无序的。

    【讨论】:

    • 啊,我明白了。嘿,又是你!谢谢你帮助我!
    • 老实说,我从另一个项目中复制了很多代码,因为它有很多我需要的东西。很高兴知道在您的帮助下我可以减少很多未使用的代码!
    猜你喜欢
    • 2014-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-14
    • 1970-01-01
    • 2011-02-09
    • 1970-01-01
    相关资源
    最近更新 更多