首页 > 解决方案 > 让用户使用字符串创建自定义格式

问题描述

我希望用户能够在其中创建自定义格式,QtWidgets.QPlainTextEdit()它将格式化字符串并将结果拆分为另一个QtWidgets.QPlainTextEdit().

例如

movie = {
    "Title":"The Shawshank Redemption",
    "Year":"1994",
    "Rated":"R",
    "Released":"14 Oct 1994",
    "Runtime":"142 min",
    "Genre":"Drama",
    "Director":"Frank Darabont",
    "Writer":"Stephen King (short story \"Rita Hayworth and Shawshank Redemption\"),Frank Darabont (screenplay)",
    "Actors":"Tim Robbins, Morgan Freeman, Bob Gunton, William Sadler",
    "Plot":"Two imprisoned men bond over a number of years, finding solace and eventual redemption through acts of common decency.",
    "Language":"English",
    "Country":"USA",
    "Awards":"Nominated for 7 Oscars. Another 21 wins & 36 nominations.",
    "Poster":"https://m.media-amazon.com/images/M/MV5BMDFkYTc0MGEtZmNhMC00ZDIzLWFmNTEtODM1ZmRlYWMwMWFmXkEyXkFqcGdeQXVyMTMxODk2OTU@._V1_SX300.jpg",
    "Ratings":  [
                    {
                        "Source":"Internet Movie Database",
                        "Value":"9.3/10"
                    },
                    {
                        "Source":"Rotten Tomatoes",
                        "Value":"91%"
                    },
                    {
                        "Source":"Metacritic",
                        "Value":"80/100"
                    }
                ],
    "Metascore":"80",
    "imdbRating":"9.3",
    "imdbVotes":"2,367,380",
    "imdbID":"tt0111161",
    "Type":"movie",
    "DVD":"15 Aug 2008",
    "BoxOffice":"$28,699,976",
    "Production":"Columbia Pictures, Castle Rock Entertainment",
    "Website":"N/A"
}

custom_format = '[ {Title} | ⌚ {Runtime} | ⭐ {Genre} |  {Released} | {Rated} ]'.format(Title=movie['Title'], Runtime=movie['Runtime'], Genre=movie['Genre'],Released=movie['Released'],Rated=movie['Rated'])

print(custom_format)

上面的这段代码很容易打印[ The Shawshank Redemption | ⌚ 142 min | ⭐ Drama | 14 Oct 1994 | R ].

但是,如果我将此代码更改为:

custom_format = '[ {Title} | ⌚ {Runtime} | ⭐ {Genre} |  {Released} | {Rated} ]'.format(Title=movie['Title'], Runtime=movie['Runtime'], Genre=movie['Genre'],Released=movie['Released'],Rated=movie['Rated'])

至:

custom_format = "'[ {Title} | ⌚ {Runtime} | ⭐ {Genre} |  {Released} | {Rated} ]'.format(Title=movie['Title'], Runtime=movie['Runtime'], Genre=movie['Genre'],Released=movie['Released'],Rated=movie['Rated'])"

请注意,整个内容都包含在“”中。因此它是一个字符串。现在这样做不会打印出我想要的格式。我将它包装在 "" 中的原因是,当我将原始文件添加custom_format到 aQtWidgets.QPlainTextEdit()时,它会将其转换为稍后不会格式化的字符串。

所以我最初的想法是,用户在QtWidgets.QPlainTextEdit(). 然后我复制该格式,打开一个包含电影 json 变量的新窗口,并将该格式粘贴到另一个QtWidgets.QPlainTextEdit()希望显示其格式正确的地方。

对此的任何帮助将不胜感激。

附加信息:

用户在QtWidgets.QPlainTextEdit().

这是用户添加自定义格式的地方

然后用户点击Test Format应该显示[ The Shawshank Redemption | ⌚ 142 min | ⭐ Drama | 14 Oct 1994 | R ]但它显示

在此处输入图像描述

标签: python-3.xpyqt5

解决方案


尝试使用完整格式命令需要一个eval(),这通常被认为不仅是不好的做法,而且是一个严重的安全问题,尤其是当输入参数完全由用户设置时。

由于字段是已知的,我认为提供整个格式行没有什么意义,最好解析格式字符串以查找关键字,然后使用关键字查找来创建输出。

class Formatter(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        layout = QtWidgets.QVBoxLayout(self)
        self.formatBase = QtWidgets.QPlainTextEdit(
            '[ {Title} | ⌚ {Runtime} | ⭐ {Genre} |  {Released} | {Rated} ]')
        self.formatOutput = QtWidgets.QPlainTextEdit()
        layout.addWidget(self.formatBase)
        layout.addWidget(self.formatOutput)
        self.formatBase.textChanged.connect(self.processFormat)
        self.processFormat()

    def processFormat(self):
        format_str = self.formatBase.toPlainText()
        # escape double braces
        clean = re.sub('{{', '', re.sub('}}', '', format_str))
        # capture keyword arguments
        tokens = re.split(r'\{(.*?)\}', clean)
        keywords = tokens[1::2]
        try:
            # build the dictionary with given arguments, unrecognized keywords
            # are just printed back in the {key} form, in order let the
            # user know that the key wasn't valid;
            values = {k:movie.get(k, '{{{}}}'.format(k)) for k in keywords}
            self.formatOutput.setPlainText(format_str.format(**values))
        except (ValueError, KeyError):
            # exception for unmatching braces
            pass

推荐阅读