如何在wxPython标签中显示熊猫数据框

时间:2020-11-08 22:21:27

标签: python-3.x pandas dataframe wxpython display

我正在尝试在wxPython选项卡中显示熊猫数据框。 我尝试了其他方法,例如在ListCtrl中使用wxPython的构建,但无法完成该工作,而且我认为使用DataFrame会更容易。

做了一些研究之后,这段代码似乎可以独立工作

import json
import pandas as pd
from IPython.core.display import display

df = pd.DataFrame(data["downloadHistory"][0])
display(df)

输出:

          titles   author                 urls
0  exampletitle1  author1  https://example.com
1  exampletitle2  author2  https://example.com

但是在下面的选项卡中,输出看起来并不漂亮。

class DownloadHistory(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent)
        df = pd.DataFrame(data["downloadHistory"][0])
        disp = display(df)

        doHiLab = wx.StaticText(self, -1, "DOWNLOAD HISTORY:", (10, 15))
        tableText = wx.StaticText(self, -1, str(disp), (10, 50))

        self.clear = wx.Button(self, label='Clear History', size=(75, 25), pos=(420, 10))

输出示例1:

       titles author         urls
0  exampletitle1  author1  https://example.com
1  exampletitle2  author2  https://example.com

输出示例2:

        titles  author           urls
0  example123456789  author123456  https://example.com/
1   exampletitle2   author2  https://example.com/12345

JSON文件:

{
   "downloadHistory": [
        {
            "titles": ["example123456789", "exampletitle2"],
            "author": ["author123456", "author2"],
            "urls": ["https://example.com/", "https://example.com/12345"]
        }
    ],
}

是否有任何原因导致选项卡中的输出混乱而不是单独出现?

另外,有没有一种有效的方法来在wxPython中显示DataFrame?

我已经尝试了更多研究,但是没有运气。

1 个答案:

答案 0 :(得分:1)

您处在正确的轨道上。有很多选择。我建议您将DataFrame分配给wx.grid,该文件显示的行和列对齐。

使用下载历史记录JSON文件:

import pandas as pd

import wx
import wx.grid

EVEN_ROW_COLOUR = '#CCE6FF'
GRID_LINE_COLOUR = '#ccc'

data = {
   "downloadHistory": [
        {
            "titles": ["example123456789", "exampletitle2"],
            "author": ["author123456", "author2"],
            "urls": ["https://example.com/", "https://example.com/12345"]
        }
    ],
}

#declare DataTable to hold the wx.grid data to be displayed
class DataTable(wx.grid.GridTableBase):
    def __init__(self, data=None):
        wx.grid.GridTableBase.__init__(self)
        self.headerRows = 1
        if data is None:
            data = pd.DataFrame()
        self.data = data

    def GetNumberRows(self):
        return len(self.data)

    def GetNumberCols(self):
        return len(self.data.columns) + 1

    def GetValue(self, row, col):
        if col == 0:
            return self.data.index[row]
        return self.data.iloc[row, col - 1]

    def SetValue(self, row, col, value):
        self.data.iloc[row, col - 1] = value

    def GetColLabelValue(self, col):
        if col == 0:
            if self.data.index.name is None:
                return 'Index'
            else:
                return self.data.index.name
        return str(self.data.columns[col - 1])

    def GetTypeName(self, row, col):
        return wx.grid.GRID_VALUE_STRING

    def GetAttr(self, row, col, prop):
        attr = wx.grid.GridCellAttr()
        if row % 2 == 1:
            attr.SetBackgroundColour(EVEN_ROW_COLOUR)
        return attr


class MyFrame(wx.Frame):
    """
    Frame that holds all other widgets
    """

    def __init__(self):
        """Constructor"""
        wx.Frame.__init__(self, None, wx.ID_ANY, "DOWNLOAD HISTORY")
        self._init_gui()
        self.Layout()
        self.Show()

    def _init_gui(self):
        # assign the DataFrame to df
        df = pd.DataFrame(data["downloadHistory"][0])
        table = DataTable(df)

        #declare the grid and assign data
        grid = wx.grid.Grid(self, -1)
        grid.SetTable(table, takeOwnership=True)
        grid.AutoSizeColumns()

        mainSizer = wx.BoxSizer(wx.VERTICAL)
        sizer = wx.BoxSizer(wx.HORIZONTAL)
        
        sizer.Add(grid, 0, wx.EXPAND)

        #add some buttons, and change methods as needed
        cancelButton = wx.Button(self, wx.ID_CANCEL, "Cancel")
        self.Bind(wx.EVT_BUTTON, self.OnCancel, cancelButton)

        proceedButton = wx.Button(self, wx.ID_OK, "Proceed")
        self.Bind(wx.EVT_BUTTON, self.OnProceed, proceedButton)

        sizerbtns = wx.BoxSizer(wx.HORIZONTAL)
        sizerbtns.Add(cancelButton, 0, wx.CENTER)
        sizerbtns.Add(proceedButton, 0, wx.CENTER)
        
        mainSizer.Add(sizer, 0, wx.ALL, 5)
        mainSizer.Add(sizerbtns, 0, wx.CENTER)
        
        sizer.SetSizeHints(self)
        self.SetSizerAndFit(mainSizer)

        self.Bind(wx.EVT_CLOSE, self.exit)

    def exit(self, event):
        self.Destroy()

    def OnCancel(self, event):
        self.Destroy()
        
    def OnProceed(self, event):
        self.Destroy()

if __name__ == "__main__":
    app = wx.App()
    frame = MyFrame()
    app.MainLoop()